我有以下源代码:
{-# LANGUAGE
FlexibleContexts,
MultiParamTypeClasses,
FunctionalDependencies
#-}
class Digit d
data Zero
data One
data Two
data Three
data Four
data Five
data Six
instance Digit Zero
instance Digit One
instance Digit Two
instance Digit Three
instance Digit Four
instance Digit Five
instance Digit Six
class Sum a b c | a b -> c, a c -> b, c b -> a
incSize :: (Digit z, Digit x, Sum x One z) => x -> z --written by me
incSize _ = undefined
intToSize :: (Digit x, Num a, Sum x One x) => a -> x -> t --inferred by GHCI
intToSize n v = intToSize (n-1) (incSize v)
intToSize' :: (Digit b, Sum b One b) => Int -> t -> b -> b --inferred by GHCI
intToSize' n v = foldr (.) id (replicate n incSize)
intToSize'' :: (Digit a, Digit b1, Digit b, Digit c, Sum a One b1, Sum b1 One b, Sum b One c) => a -> c --inferred by GHCI
intToSize'' = incSize . incSize . incSize
本质上,目标是获取Int
并将其转换为上面定义的数据类型之一。该功能incSize
正常工作;它将大小增加一。该功能inToSize''
也有效;它将给定数字增加3。但是,两者都intToSize
不起作用intToSize'
;GHCI 如上所述推断它们的类型(显然,a+1 =/= a)。我不确定为什么手动编写组合可以正常工作,而其他任何事情都会失败(我确定为无法编译的函数,但无论何时使用它们都会出错。)使用应该如下所示:
> :t intToSize'' (undefined :: Zero)
> intToSize'' (undefined :: Zero) :: Three
然而,最终目标是编写一个函数,该函数接受一个列表,并给出一个数据类型,该数据类型将列表的长度编码为其类型(本质上是一个向量):
data Vect s v = Vect v
instance forall s v . Show (Vect s v) where
--toInt is a function which takes a type number and returns its data level value
show (Vect v) = "Vect " ++ (show . toInt) (undefined :: s) ++ show v
> let l = [1,2,3,4,5]
> vector l
> Vect 5 [1,2,3,4,5]
您可能已经注意到缺少一些代码;看起来很无聊,所以我把它放在底部。
instance Sum Zero Zero Zero
instance Sum Zero One One
instance Sum Zero Two Two
instance Sum Zero Three Three
instance Sum Zero Four Four
instance Sum Zero Five Five
instance Sum Zero Six Six
instance Sum One Zero One
instance Sum One One Two
instance Sum One Two Three
instance Sum One Three Four
instance Sum One Four Five
instance Sum One Five Six
instance Sum Two Zero Two
instance Sum Two One Three
instance Sum Two Two Four
instance Sum Two Three Five
instance Sum Two Four Six
instance Sum Three Zero Three
instance Sum Three One Four
instance Sum Three Two Five
instance Sum Three Three Six
instance Sum Four Zero Four
instance Sum Four One Five
instance Sum Four Two Six
instance Sum Five Zero Five
instance Sum Five One Six
instance Sum Six Zero Six