I don't really get what is wrong with the following code.
data TypeA = TypeA class MyClass a where myClassFunction :: a -> String instance MyClass TypeA where myClassFunction TypeA = "TypeA" bar :: (MyClass a) => String -> a bar "TypeA" = TypeA I get following error:
Couldn't match expected type ‘a’ with actual type ‘TypeA’ ‘a’ is a rigid type variable bound by the type signature for bar :: MyClass a => String -> a at test.hs:9:8 Relevant bindings include bar :: String -> a (bound at test.hs:10:1) In the expression: TypeA In an equation for ‘bar’: bar "TypeA" = TypeA Failed, modules loaded: none. I'm afraid that I'm missing something crucial about Haskell type system.
43 Answers
(MyClass a) => String -> a Means that the function can return any a type that's asked from it. Your implementation returns one particular type that satisfies that constraint. This is more obvious with the explicit signature:
bar :: forall a. (MyClass a) => String -> a Read plainly, that's for every type a that satisfies MyClass, this function will take a string and return a value of that type. Your version would assume exists a instead.
The function type MyClass a => String -> a indicates a function that can return a value of any type (with an instance of MyClass) of the caller's choosing. There is no apparent way, for example, to return a value of type Int (again, assuming MyClass Int is defined) given the value TypeA
a should be any type, and yet you return a specific type. One way around it is to use the extension existentialQuantification. Or you extend your class as the following:
data TypeA = TypeA class MyClass a where myClassFunction :: a -> String foo :: String -> a instance MyClass TypeA where myClassFunction TypeA = "TypeA" foo "TypeA" = TypeA foo _ = error "unknown" bar :: (MyClass a) => String -> a bar = foo So when you call the bar function:
bar "TypeA" :: TypeA 1