变量参数,使用Type Families而不是Multi-param Typeclasses

时间:2011-11-06 23:48:14

标签: haskell variadic-functions type-families

这是我所拥有的,用MultiParamTypeClasses表示:

class ListResultMult r a where
  lstM :: a -> [a] -> r

listM :: ListResultMult r a => a -> r
listM a = lstM a []


instance ListResultMult r a => ListResultMult (a -> r) a where
  lstM a as x = lstM x $ a:as

instance ListResultMult [a] a where
  lstM a as = reverse $ a:as

instance Show a => ListResultMult (IO ()) a where
  lstM a as = print . reverse $ a:as

这是我尝试过的,使用TypeFamilies(TypeSynonymInstances没有帮助):

class ListResultFam r where
  type Elem r :: *
  lstF :: Elem r -> [Elem r] -> r

listFam :: ListResultFam r => Elem r -> r
listFam a = lstF a []


-- Illegal type synonym family application in instance: Elem r -> r
-- in the instance declaration for `ListResultFam (Elem r -> r)'
instance ListResultFam r => ListResultFam (Elem r -> r) where
  type Elem (Elem r -> r) = Elem r
  lstF a as x = lstF x $ a:as

instance ListResultFam [a] where
  type Elem [a] = a
  lstF a as = reverse $ a:as

有没有办法通过Type Families实现这一目标?为什么这是一个“非法”类型的同义词家庭应用程序?

1 个答案:

答案 0 :(得分:8)

类型族不是多参数类型的替代,而是替换函数依赖。

这是因为类型族允许从一种类型到另一种类型的映射,这类似于多参数类型类的函数依赖性。即:

class Collection col e | col -> e where
   getHead :: col -> e

instance Collection [a] a where
   getHead = head

可以用类型族表示为:

class Collection col where
  type CollectionHead col :: *
  getHead :: col -> CollectionHead col

instance Collection [a] where
   type CollectionHead [a] = a
   getHead = head

但是,它们无法替换没有功能依赖性的多参数类型。例如

class Converter a b where
  convert :: a -> b

instance Converter Int String where
  convert = show

instance Converter Int [Int] where
  convert x = [x]

无法通过删除b参数和使用类型系列来完成。你可以这样做:

class Converter a where
   type Target a :: *
   convert :: a -> Target a

instance Converter Int where
   type Target Int = String
   convert = show

但是无法编写第二个实例,因为它需要重复的实例Converter Int


关于你的程序,你可以立即看到没有功能依赖,只有多个参数类型类。因此,您不能直接转换为使用此类型的家庭。

相关问题