{-# LANGUAGE RankNTypes, ScopedTypeVariables, NoMonomorphismRestriction #-}
type CList a = (forall t . (a -> t -> t) -> t -> t)
ccons :: forall a . a -> CList a -> CList a
ccons h t = (\ c n -> c h (t c n))
cnil :: forall h . CList h
cnil = (\ c n -> n)
cToList :: forall a . CList a -> [a]
cToList list = list (:) []
cFromList :: forall a . [a] -> CList a
cFromList = foldr ccons cnil
main = print (cToList (cFromList [1,2,3]))
我理解它没有编译的原因与forall
上ccons
的使用有关。注释ccons
类型将使其编译,但ccons
的类型很尴尬。解决问题的正确方法是什么?
test.hs:15:23:
Couldn't match type ‘(a -> t -> t) -> t -> t’
with ‘forall t1. (a -> t1 -> t1) -> t1 -> t1’
Expected type: a
-> ((a -> t -> t) -> t -> t) -> (a -> t -> t) -> t -> t
Actual type: a -> CList a -> (a -> t -> t) -> t -> t
Relevant bindings include
cFromList :: [a] -> CList a (bound at test.hs:15:5)
In the first argument of ‘foldr’, namely ‘ccons’
In the expression: foldr ccons cnil
答案 0 :(得分:3)
你为什么要使用ccons
? cFromList
只是翻转foldr
cFromList :: [a] -> CList a
cFromList xs op seed = foldr op seed xs
答案 1 :(得分:2)
正如@Daniel Wagner指出的那样,仅仅使用newtype
代替type
解决了这个问题:
newtype CList a = CList { runCList :: (forall t . (a -> t -> t) -> t -> t) }
ccons :: forall h . h -> CList h -> CList h
ccons h t = CList (\ c n -> c h (runCList t c n))
cnil :: forall h . CList h
cnil = CList (\ c n -> n)
cToList :: forall a . CList a -> [a]
cToList list = runCList list (:) []
cFromList :: forall a . [a] -> CList a
cFromList list = (foldr ccons cnil list)
main = print (cToList (cFromList [1,2,3]))
显然我之前也被告知过,但我真的不记得也没找到问题。对不起伙计们:(