这是我所拥有的,用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实现这一目标?为什么这是一个“非法”类型的同义词家庭应用程序?
答案 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
。
关于你的程序,你可以立即看到没有功能依赖,只有多个参数类型类。因此,您不能直接转换为使用此类型的家庭。