请注意这个程序:
{-# LANGUAGE RankNTypes #-}
import Prelude hiding (sum)
type List h = forall t . (h -> t -> t) -> t -> t
sum_ :: (Num a) => List a -> a
sum_ = \ list -> list (+) 0
toList :: [a] -> List a
toList = \ list cons nil -> foldr cons nil list
sum :: (Num a) => [a] -> a
-- sum = sum_ . toList -- does not work
sum = \ a -> sum_ (toList a) -- works
main = print (sum [1,2,3])
两种 sum 的定义在方程推理上是相同的。然而,编译第二个定义可行,但第一个定义不行,会出现以下错误:
tmpdel.hs:17:14:
Couldn't match type ‘(a -> t0 -> t0) -> t0 -> t0’
with ‘forall t. (a -> t -> t) -> t -> t’
Expected type: [a] -> List a
Actual type: [a] -> (a -> t0 -> t0) -> t0 -> t0
Relevant bindings include sum :: [a] -> a (bound at tmpdel.hs:17:1)
In the second argument of ‘(.)’, namely ‘toList’
In the expression: sum_ . toList
看起来 RankNTypes
会破坏等式推理。在 Haskell 中有没有不破坏它的情况下使用 church 编码列表的方法?
Rank2Types
和RankNTypes
,即使它们目前执行相同的操作)。 - Daniel Wagnerhead :: List (Maybe a) a -> Maybe a; head f = f Just Nothing
或者unsafeHead :: List a a -> a; unsafeHead f = f id undefined
。 - Daniel Wagner[a] -> List a
是 GHC 中实际上不存在的类型(参见https://dev59.com/oo3da4cB1Zd3GeqPzGX6#31629197),这使得sum_ . toList
的类型不正确。 - András Kovács