Search code examples
typeclasspurescript

Type classes, instances and wrappers


can somebody explain to me why this(version 1) compiles while the version below(version 2) does not.

-- version 1 (compiles)
module Chapter2 where

import Debug.Trace

data Wrapper a = Wrapper a
instance showWrapper :: (Show a) => Show (Wrapper a) where
    show (Wrapper w) = "Wrapper ( " ++ (show w) ++ " )"

foo :: Number -> Number -> Number -> Number
foo a b c = a + b + c
foo1 = foo 2
foo2 = foo 1 2

class ExecFn a where
    exec :: a -> Number

instance execFn1 :: ExecFn (Number -> Number -> Number) where
    exec a = 99

main = do
    let x = exec foo1
    trace "Hello"

This does not compile

-- Version 2 (does not compile)
module Chapter2 where

import Debug.Trace

data Wrapper a = Wrapper a
instance showWrapper :: (Show a) => Show (Wrapper a) where
    show (Wrapper w) = "Wrapper ( " ++ (show w) ++ " )"

foo :: Number -> Number -> Number -> Number
foo a b c = a + b + c
foo1 = foo 2
foo2 = foo 1 2

class ExecFn a b where
    exec :: a -> Wrapper b

instance execFn1 :: ExecFn (Number -> Number -> Number) Number where
    exec a = Wrapper 99

main = do
    let x = exec foo1
    trace "Hello"    

and gives me this error

Error at src/Chapter2.purs line 3, column 1 - line 5, column 1:
  No instance found for Chapter2.ExecFn (Prim.Number -> Prim.Number -> Prim.Number) u8735

So how can I make a version similar to my version 2 so that I can put my result into a wrapper?


Solution

  • The type of x is underconstrained, which is why there is an unknown type variable appearing in the error message. psc will not try to instantiate a type variable when searching for a type class instance. This can sometimes be an issue when using multi parameter type classes without something like functional dependencies to help disambiguate types (purescript-transformers has the same issue, for example). For now, you need to add a type signature, or use x in such a way that will disambiguate the type b.

    So if you add the expected type for the let

    let x = exec foo1 :: Wrapper Number
    

    this should help