Hello i have a type with a type parameter:
data A=A1| A2 deriving (Show)
data B=B1| B2 deriving(Show)
data C a=C{var::a,var2::Int}
getters=[show . var,show .var2]
I get the following error in the getters
at show . var
:
Ambiguous type variable `a0' arising from a use of `show'
prevents the constraint `(Show a0)' from being solved.
Relevant bindings include
getters:: [Worker a0 -> String]
Do i have to explicitly state the type ,something like : show. (var::B)
.I do not really understand the error since both types A
and B
are implementing Show
Edit: updated below to answer your follow-up question.
To answer your original question, this is just a situation where the type checker needs a little help. You can get your code to type check by adding an explicit signature for getters
, as @WillemVanOnsem has suggested:
data A = A1 | A2 deriving (Show)
data B = B1 | B2 deriving (Show)
data C a = C { var :: a, var2 :: Int }
getters :: (Show a) => [C a -> String]
getters = [show . var, show . var2]
or, alternatively, by turning on the NoMonomorphismRestriction
GHC extension, as @DanielWagner points out. After doing either of these, the following works fine:
> map ($ C A1 10) getters
["A1","10"]
> map ($ C B2 10) getters
["B2","10"]
>
This signature doesn't make getters
a "method", if your comment about methods was directed at Willem. It's still a polymorphic expression with type [C a -> String]
(for any type a
with a Show a
constraint).
Update: As per your comments, you think you want to define a data type with a constraint on the type of one or more of its fields. (You don't actually want to do this -- you just think you do -- but who am I to stop you?)
So, to do this, you'll need to enable the DatatypeContexts
extension and write:
{-# LANGUAGE DatatypeContexts #-}
class Mytypeclass a where
whatever :: a -> String
data Mytypeclass a => MyType a = M { var :: a, var2 :: a }
The compiler will generate a warning that this extension was deprecated because it was widely considered a misfeature and removed from the language.
Now, you can define:
getters = [whatever . var, whatever . var2]
This will give you an error, though a different error message than before, after which you can either add the signature:
getters :: (Mytypeclass a) => [MyType a -> String]
getters = [whatever . var, whatever . var2]
or else enable the NoMonomorphismRestriction
extension in order to get it to compile, just like before.