【发布时间】:2015-07-04 01:33:26
【问题描述】:
我正在尝试编写一个filterA :: (ArrowChoice arr) => arr a Bool -> arr [a] [a] 函数,该函数从f :: arr a Bool 返回False 的列表中删除每个元素。这就是我目前所拥有的
listcase [] = Left ()
listcase (x:xs) = Right (x, xs)
filterA f = arr listcase >>>
arr (const []) ||| (first (f &&& arr id) >>>
arr (\((b,x),xs) -> if b then
x : (filterA f xs)
else filterA f xs
))
现在使用 (->) a 箭头测试它时可以使用,如下所示:
λ> filterA (== 8) [8,9]
[8]
但是,对于像 Kleisli Arrows 这样的人来说,它不起作用
λ> runKleisli (Kleisli $ filterA (== 8)) (return [8,9] :: [IO Int])
<interactive>:160:47:
Couldn't match expected type `IO Int' with actual type `[t0]'
In the first argument of `return', namely `[8, 9]'
In the second argument of `runKleisli', namely
`(return [8, 9] :: [IO Int])'
In the expression:
runKleisli (Kleisli $ filterA (== 8)) (return [8, 9] :: [IO Int])
并且在添加类型签名filterA :: (Arrow arr) => arr a Bool -> arr [a] [a] 或filterA :: (ArrowChoice arr) => arr a Bool -> arr [a] [a] 时,会抛出此错误:
arrows.hs:11:22:
Could not deduce (arr ~ (->))
from the context (Arrow arr)
bound by the type signature for
filterA :: Arrow arr => arr a Bool -> arr [a] [a]
at arrows.hs:7:12-51
`arr' is a rigid type variable bound by
the type signature for
filterA :: Arrow arr => arr a Bool -> arr [a] [a]
at arrows.hs:7:12
Expected type: [a] -> [a]
Actual type: arr [a] [a]
The function `filterA' is applied to two arguments,
but its type `arr a Bool -> arr [a] [a]' has only one
In the second argument of `(:)', namely `(filterA f xs)'
In the expression: x : (filterA f xs)
我不明白为什么。我错过了什么吗?
编辑: @jaket 的评论有效(我想这有点愚蠢),但类型签名仍然不匹配。 我还更新了代码以更紧凑(尽管仍然出现相同的错误)
filterA f = arr listcase >>>
arr (const []) ||| (arr toEither >>>
(filterA f) ||| (second (filterA f) >>> arr uncurry (:)))
where toEither (x, xs) = if f x then Right (x, xs) else Left xs
顺便说一下,GHC 将类型推断为filterA :: (a -> Bool) -> [a] -> [a]。
【问题讨论】:
-
runKleisli (Kleisli $ filterA (== 8)) [8, 9]? -
@jaket 修复了我猜的问题。但是,它不能修复类型签名的事情
-
在您的更新中,您使用
f就好像它是if f x then ...中的一个函数 - 使用f是 GHC 坚持仅在arr类型为事实上(->)。请参阅下面的答案。 -
另外,请注意 @jaket 的
runKleisli (Kleisli $ filterA (== 8)) [8, 9]版本不是您想要的 - 它绑定到 monad[],即使使用正确键入的filterA。