Reputation: 133
I'm learning Haskell. Why can't I change Person
to type variable a
in the method signature of getName
{-# LANGUAGE DeriveGeneric #-}
module Main where
import GHC.Generics
data Person = Person { id :: Int
, name :: String
, age :: Int }
deriving (Generic, Show)
p = from $ Person 12 "J" 12
getName :: (Rep Person) x -> String
-- getName :: Generic a => (Rep a) x -> String
----^ Err: Couldn't match type ‘Rep a0’ with ‘Rep a
getName f = concat [ moduleName f
, "_"
, datatypeName f
]
n = getName p
Upvotes: 4
Views: 111
Reputation: 24802
Rep
is an associated type-synonym i.e. the actual type can be anything depending on the implementation of the specific type-class instance. There is no guarantee that Rep a
for any arbitrary a
is a type that is compatible with the type required by the function moduleName
.
Rep Person
works because the compiler is able to check that the associated type for the type-class instance of Generic Person
fits the type expected by moduleName
(which is Datatype d => t d (f :: * -> *) a
).
Instead of using Rep a
you can instead use
getName :: Datatype d => t d (f :: * -> *) a -> String
getName f = concat [ moduleName f
, "_"
, datatypeName f
]
Although you also need to enable the KindSignatures
extension.
Upvotes: 2
Reputation: 52029
Just omit the type signature for getName
.
Running your code in a ghci session yields this:
ghci> :t getName
getName :: Datatype d => t d f a -> [Char]
ghci> getName p
"Lib9_Person"
ghci> :t getName p
getName p :: [Char]
Note: My code resides in the module Lib9
which explains the output for getName p
.
If you want to give it a type signature, enable KindSignatures
and use:
getName :: Datatype d => (t :: * -> (* -> *) -> * -> *) d f a -> [Char]
Upvotes: 1