Reputation: 323
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.
Upvotes: 10
Views: 6903
Reputation: 71
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
Upvotes: 0
Reputation: 39370
(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.
Upvotes: 11
Reputation: 531165
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
Upvotes: 6