We can write single, comprehensive examples for the parameters of the form *:
class MyClass d where
f :: d -> Int
instance MyClass (Maybe d) where
f _ = 3
test1 :: Maybe d -> Int
test1 x = f x
This compiles just fine and note that we don’t need (restriction MyClass (Maybe d)) for test1, because the compiler finds the appropriate instance for any Maybe d.
We can even write a comprehensive instance for class parameters that are type constructors:
class MyClass2 (a :: * -> *) where
g :: Tagged (a Int) Int
instance MyClass2 a where
g = Tagged 3
test2 :: Int
test2 = untag (g :: Tagged (Maybe Int) Int)
This also compiles fine, and test2 does not need to (limitation MyClass2 Maybe), because the compiler finds the corresponding instance.
Consider the following toy code to calculate the length of a list of (advanced) type:
{-# LANGUAGE TypeOperators,
DataKinds,
KindSignatures,
GADTs,
FlexibleInstances,
FlexibleContexts,
ScopedTypeVariables #-}
import Data.Tagged
import Data.Proxy
data HList :: [*] -> * where
HNil :: HList '[]
HCons :: a -> HList as -> HList (a ': as)
class ListLen a where
len :: Tagged a Int
instance ListLen (HList '[]) where
len = Tagged 0
instance (ListLen (HList as)) => ListLen (HList (a ': as)) where
len = Tagged (1+(untag (len :: Tagged (HList as) Int)))
test3 :: Int
test3 = untag (len :: Tagged (HList '[Int, Double, Integer]) Int)
test4 :: (Proxy (HList qs)) -> Int
test4 (_ :: Proxy (HList qs)) = untag (len :: Tagged (HList qs) Int) -- error occurs here
This results in an error:
No instance for (ListLen (HList qs))
arising from a use of `len'
Possible fix: add an instance declaration for (ListLen (HList qs))
...
If we comment out the signature for test4, GHCi will display the type as
test4 :: (ListLen (HList qs)) => (Proxy (HList qs)) -> Int
. , ListLen, : " " "". , ListLen, [*] (.. HList ListLen ).
test4, test3 : ( ) ('[Int,Double,Integer]) , , .
, , . , - , GHC . , , ? ?
, GHC , [*]?
GHC 7.4.2. . .