以下函数使用递归方案库从列表中实现了良好的旧过滤器函数。
import Data.Functor.Foldable
catafilter :: (a -> Bool) -> [a] -> [a]
catafilter p = cata alg
where
-- alg :: ListF a [a] -> [a]
alg Nil = []
alg (Cons x xs) = if (p x) then x : xs else xs
它编译并且一个简短的测试catafilter odd [1,2,3,4]
是成功的。但是,如果我取消注释类型签名,alg
我会收到以下错误:
src/cata.hs:8:30: error:
• Couldn't match expected type ‘a’ with actual type ‘a1’
‘a1’ is a rigid type variable bound by
the type signature for:
alg :: forall a1. ListF a1 [a1] -> [a1]
at src/cata.hs:6:5-29
‘a’ is a rigid type variable bound by
the type signature for:
catafilter :: forall a. (a -> Bool) -> [a] -> [a]
at src/cata.hs:3:1-39
• In the first argument of ‘p’, namely ‘x’
In the expression: (p x)
In the expression: if (p x) then x : xs else xs
• Relevant bindings include
xs :: [a1] (bound at src/cata.hs:8:18)
x :: a1 (bound at src/cata.hs:8:16)
alg :: ListF a1 [a1] -> [a1] (bound at src/cata.hs:7:5)
p :: a -> Bool (bound at src/cata.hs:4:12)
catafilter :: (a -> Bool) -> [a] -> [a] (bound at src/cata.hs:4:1)
|
8 | alg (Cons x xs) = if (p x) then x : xs else xs
| ^
SO question type-signature-in-a-where-clause的答案 建议使用ScopedTypeVariables扩展。对Why-is-it-so-uncommon-to-use-type-signatures-in-where-clauses的最后一个答案中的评论 建议使用forall量化。
所以我补充说:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
在我的模块顶部,并为alg尝试了不同的类型签名,例如:
alg :: forall a. ListF a [a] -> [a]
或者
在catlist类型签名中alg :: forall b. ListF b [b] -> [b]
添加一个forall 。没有编译!
问题:为什么我不能为alg指定类型签名?