0
Error found:
in module Test
at /Users/arahael/dev/test/test.purs line 14, column 37 - line 14, column 59

  Could not match constrained type

    (Spreadable a0) => Array a0 -> Int

  with type

    (Spreadable a1) => Array a1 -> Int


while trying to match type (Spreadable a0) => Array a0 -> Int
  with type (Spreadable a1) => Array a1 -> Int
while checking that expression mkFn2 get_biscuits
  has type Fn2 String (forall a. (Spreadable a) => Array a -> Int) Int
in value declaration packetMaker

where a1 is a rigid type variable
      a0 is a rigid type variable

See https://github.com/purescript/documentation/blob/master/errors/ConstrainedTypeUnified.md for more information,
or to contribute content related to this error.

Code as below:

module Test                                                                                                            
where                                                                                                                  


foreign import data Fn2 :: * -> * -> * -> *                                                                            
foreign import mkFn2 :: forall a b c. (a -> b -> c) -> Fn2 a b c                                                       

class Spreadable a

newtype Packet = Packet { getBiscuits :: Fn2 String (forall a. (Spreadable a) => Array a -> Int) Int }

get_biscuits :: String -> (forall a. (Spreadable a) => Array a -> Int) -> Int
get_biscuits _ _ = 42
packetMaker = Packet { getBiscuits: mkFn2 ( get_biscuits ) }                                                      

In what circumstances might a '(forall a. a)' be incompatible? (To rephrase the question: What's the difference between a0 and a1 here in the example? I intended these functions to be polymorphic for a)


Update: I now have it working, for the following code:

module Test
where

class Spreadable a

newtype Packet = Packet { getBiscuits :: String -> (forall a. (Spreadable a) => Array a -> Int) ->  Int }

get_biscuits :: String -> (forall a. (Spreadable a) => Array a -> Int) -> Int
get_biscuits _ _ = 42

packetMaker :: Packet
packetMaker = Packet { getBiscuits: \a b -> get_biscuits a b}

BUT, I need this to be a javascript-style "Fn2" function, ie, a function that takes two argumetns, and is not curried; and I can't get it to work with Fn2. Any suggestions as to why?

Arafangion
  • 11,517
  • 1
  • 40
  • 72
  • Btw, this is very likely to be the same issue as http://stackoverflow.com/questions/43794555/why-dont-these-types-unify-when-using-type-constraints-and-a-typeclass-instance so I am missing something. Hopefully if I understand this error, I will understand that question. – Arafangion May 06 '17 at 07:05
  • Try eta expanding `get_biscuits` to `\s f -> get_biscuits s f`. – Phil Freeman May 07 '17 at 19:43
  • @PhilFreeman: That gives me two questions, 1) Why should that make a difference (I ask _because_ there is indeed a difference, but I don't know why), and 2) What should I do with the new error? Specifically, I now get a 'could not match constrained type' between `(Spreadable a0) => Array a0 -> Int` and `Array a1 -> Int`. Thanks! – Arafangion May 08 '17 at 00:09
  • The compiler needs some help in some situations involving rank N types. This help can come in the form of eta expanding functions (which causes the type checker to check the function correctness in a slightly different way) or adding more type annotations. I suspect you might need to do the latter in this case. However, I'd also suggest you reconsider your data types, there might be a simpler solution. – Phil Freeman May 08 '17 at 05:47
  • @PhilFreeman: I definitely feel that I need to study rank N types properly - this feels like monads all over again. However, in this case, I notice that the error message now discards the constraint - which actually appears to be an mistake. (I Specifically wanted the constraint on the type denoted by `a`, so the new `Array a1 -> Int` has lost it's constraint, somehow). I don't know enough to know if this is an improvement, or a step backwards. How would you reconsider the data types? Consider that I want a "getBiscuits" to be a "Fn2" that takes a callback and ultimately returns an int. – Arafangion May 08 '17 at 05:58
  • That is, accepting a callback accepting an "array of spreadables", and which returns an int, and ultimately returns an int. – Arafangion May 08 '17 at 06:06
  • It should be clarified that I'm not intentionally making use of "rankNTypes", (but I do want to understand it regardless.) – Arafangion May 08 '17 at 06:36
  • @PhilFreeman: Thanks for your answer, with it I got a version working *without* Fn2, but I want getBiscuits to be a non-curried function. – Arafangion May 13 '17 at 03:47

0 Answers0