So, I'm trying to implement a polyvarian ZipWithN, as described here . Unfortunately, the Paczesiowa code seems to have been compiled with legacy versions of both ghc and HList, so trying to figure out how this works, I also ported it to the most recent versions of the two (ghc-7.8.3 and HList-0.3. 4.1 at present). It was fun.
In any case, I encountered an error that Google does not help me fix once, in the definition of the curryN' intermediate function. The concept of curryN' is simple: it takes a natural number of type N (or, strictly speaking, a value of this type) and a function f , whose first argument is an HList of length N , and returns the function N -ary, which takes an HList from its first arguments N and returns f applied to this HList. He is curry , but polyvariadic.
It uses three helper functions / classes:
First ResultType / ResultType as I defined here . ResultType takes one function as an argument and returns the type of this function after applying it to as many arguments as possible. (Strictly speaking, again, it returns an undefined value of this type).
For instance:
ghci> :t resultType (++) resultType (++) :: [a] ghci> :t resultType negate resultType negate :: (ResultType a result, Num a) => result
(The latter case, because if a is a function of type x -> y , resultType would have to return y , so it is not ideally applied to polymorphic functions.)
The second two: Eat / Eat and MComp / MComp , defined together (along with curryN' ) in one file (along with broken curryN' ), like this .
Eat The first argument is a value whose type is a positive integer N , and returns a function that takes N arguments and returns them to an HList:
ghci> :t eat (hSucc (hSucc hZero)) eat (hSucc (hSucc hZero)) :: x -> x1 -> HList '[x, x1] ghci> eat (hSucc (hSucc hZero)) 5 "2" H[5, "2"]
As far as I can tell, it works just fine. MComp is a polyvarian layout feature. It takes two functions: f and g , where f takes a number of arguments N It returns a function that takes N arguments, applies f to all of them, and then applies g to f . (The order of functions is parallel (>>>) more than (.) )
ghci> :t (,,) `mcomp` show (,,) `mcomp` show :: (Show c, Show b, Show a) => a -> b -> c -> [Char] ghci> ((,,) `mcomp` show) 4 "str" 'c' "(4,\"str\",'c')"
Like ResultType , it βbreaksβ functions whose return types are type variables, but since I only plan to use it on Eat (whose final return type is just an HList ), it should work (It seems that Paczesiowa thinks so). And this happens if the first Eat argument is fixed:
\f -> eat (hSucc (hSucc hZero)) `mcomp` f
works great.
curryN' however is defined as follows:
curryN' nf = eat n `mcomp` f
Trying to load this into ghci, however, gets this error:
Part3.hs:51:1: Could not deduce (Eat n '[] f0) arising from the ambiguity check for 'curryN'' from the context (Eat n '[] f, MComp f cp d result, ResultType f cp) bound by the inferred type for 'curryN'': (Eat n '[] f, MComp f cp d result, ResultType f cp) => Proxy n -> (cp -> d) -> result at Part3.hs:51:1-29 The type variable 'f0' is ambiguous When checking that 'curryN'' has the inferred type 'forall f cp d result (n :: HNat). (Eat n '[] f, MComp f cp d result, ResultType f cp) => Proxy n -> (cp -> d) -> result' Probable cause: the inferred type is ambiguous Failed, modules loaded: Part1.
Thus, it is clear that Eat and MComp do not play as well as I hope. By the way, this is significantly different from the error that mcomp (+) (+1) gives, which complains about overlapping instances for MComp .
In any case, an attempt to find information about this error did not lead me to anything useful - with the biggest obstacle for my own debugging was that I have no idea what a variable of type f0 , even if it does not appear in any of the signatures ghci infers types or contexts.
My best guess is that MComp has difficulty MComp through the Eat polymorphic return type (even though it is fixed by a natural type number). But if so, I donβt know how I would fix it.
Additionally (and bizarrely for me), if I try to combine Part1.hs and Part2.hs into one file , I still get an error message ... but another
Part3alt.hs:59:12: Overlapping instances for ResultType f0 cp arising from the ambiguity check for 'curryN'' Matching givens (or their superclasses): (ResultType f cp) bound by the type signature for curryN' :: (MComp f cp d result, Eat n '[] f, ResultType f cp) => Proxy n -> (cp -> d) -> result at Part3alt.hs:(59,12)-(60,41) Matching instances: instance result ~ x => ResultType x result -- Defined at Part3alt.hs:19:10 instance ResultType y result => ResultType (x -> y) result -- Defined at Part3alt.hs:22:10 (The choice depends on the instantiation of 'cp, f0') In the ambiguity check for: forall (n :: HNat) cp d result f. (MComp f cp d result, Eat n '[] f, ResultType f cp) => Proxy n -> (cp -> d) -> result To defer the ambiguity check to use sites, enable AllowAmbiguousTypes In the type signature for 'curryN'': curryN' :: (MComp f cp d result, Eat n [] f, ResultType f cp) => Proxy n -> (cp -> d) -> result Failed, modules loaded: none.
Again with the mysterious variable f0 . I admit that I overdid it a bit here with all this type of hackers, so if someone could help me figure out what the problem is and more importantly, how can I fix it (if so, hopefully maybe) I would be incredibly grateful.
Final note: the reasons these two files are called Part1 and Part3 are because Part2 contains some helper functions used in zipWithN but not curryN' . For the most part, they work fine, but there are a few oddities that I might ask about later.