Pattern matching on promoted types

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. . .

+5
1

, , .

data Proxy a where
  Proxy :: ListLen a => Proxy

data Proxy a where
  Proxy :: Tagged a Int -> Proxy a

test4 :: (Proxy (HList qs)) -> Int
test4 (Proxy len) = untag len

, , Proxy, ( ). Proxy.

, len ( Data.List.length).

len :: HList a -> Int
len l = len' l 0
  where
    len' :: HList a -> Int -> Int
    len' HNil a = a
    len' (HCons _ xs) a = len' xs $! a + 1
+2

All Articles