所以,只是为了好玩,我一直在使用Peano数在Haskell中玩一个CountedList类型,并使用智能构造函数。
对我来说,类型安全的head
和tail
似乎非常酷。
我觉得我已经达到了自己知道如何做的极限。
{-# LANGUAGE EmptyDataDecls #-}
module CountedList (
Zero, Succ, CountedList,
toList, ofList,
empty, cons, uncons,
head, tail,
fmap, map, foldl, foldr, filter
) where
import qualified List (foldr, foldl, filter)
import Prelude hiding (map, head, foldl, foldr, tail, filter)
data Zero
data Succ n
data CountedList n a = CL [a]
toList :: CountedList n a -> [a]
toList (CL as) = as
ofList :: [a] -> CountedList n a
ofList [] = empty
ofList (a:as) = cons a $ ofList as
empty :: CountedList Zero a
empty = CL []
cons :: a -> CountedList n a -> CountedList (Succ n) a
cons a = CL . (a:) . toList
uncons :: CountedList (Succ n) a -> (a, CountedList n a)
uncons (CL (a:as)) = (a, CL as)
head :: CountedList (Succ n) a -> a
head = fst . uncons
tail :: CountedList (Succ n) a -> CountedList n a
tail = snd . uncons
instance Functor (CountedList n) where
fmap f = CL . fmap f . toList
map :: (a -> b) -> CountedList n a -> CountedList n b
map = fmap
foldl :: (a -> b -> a) -> a -> CountedList n b -> a
foldl f a = List.foldl f a . toList
foldr :: (a -> b -> b) -> b -> CountedList n a -> b
foldr f b = List.foldr f b . toList
filter :: (a -> Bool) -> CountedList n a -> CountedList m a
filter p = ofList . List.filter p . toList
(抱歉如果有任何转录错误 - 我最初用我的Haskell编译器写的机器目前已经出了问题)
我所做的大部分编译都没有问题,但在使用ofList
和filter
时会遇到问题。我认为我知道原因 - 当我说ofList :: [a] -> CountedList n a
时,我是在说ofList :: forall n . [a] -> CountedList n a
- 即创建的列表可以是任何所需的计数类型。我想要编写的等价于伪类型ofList :: exists n . [a] -> CountedList n a
,但我不知道该如何实现。
是否有一种解决方法可以让我像想象中那样编写ofList
和filter
函数,或者我已经达到了使用这个功能的极限?我有一种感觉,我可能漏掉了某些存在类型的技巧。