我正在嘗試編寫filterA :: (ArrowChoice arr) => arr a Bool -> arr [a] [a]
函數,該函數從列表中刪除每個元素,其中f :: arr a Bool
返回False
。這是我迄今爲止Haskell Control.Arrow:試圖寫一個filterA函數
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箭似
λ> 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
@jaket修復了我的猜測。然而,它並沒有修復類型簽名的東西 – tolUene
在你的更新中,你使用'f'就好像它是'如果fx那麼...'中的函數那樣''使用'f'就是爲什麼GHC堅持這個函數只有當'arr'類型實際上是'( - >)'時,纔會檢測類型。請參閱下面的答案。 –