私は現在、 JohnHughesによるProgrammingwith Arrowsの論文を読んでおり、セクション2.5の20ページの最初の演習ですでに困惑しています。
自由に使える型クラスと型クラス、および型を介した関数、流れ関数Arrow
、モナディック関数のインスタンスがあります。ArrowChoice
[a] -> [b]
a -> m b
Kleisli
mapA
例が示されました:
mapA f = arr listcase >>>
arr (const []) ||| (f *** mapA >>> arr (uncurry (:)))
これが試みです:
listcase :: [a] -> (Either () (a,[a]))
listcase [] = Left ()
listcase (x:xs) = Right (x,xs)
helper :: (Bool,a) -> [a] -> Either (a,[a]) [a]
helper (True,x) y = Left (x,y)
helper (False,x) y = Right y
test :: Arrow a => (b -> Bool) -> a (b,c) ((Bool,b), c)
test p = first (arr p &&& arr id)
filterA :: Arrow a => (b -> Bool) -> a [b] [c]
filterA p = f >>> (g ||| (h >>> (j ||| (filterA p))))
where f = arr listcase
g = arr (const [])
h = test p >>> (uncurry helper)
j = (arr id *** (filterA p)) >>> (arr (uncurry (:)))
この無駄な試みの背後にある(ブルートフォース)理論的根拠は次のとおりです。次の2つの選択肢があります:filterA
likelistcase
とmap
、述語を適用した結果p
。map
それは、リストをチェックし、を使用してEither値を返すように開始しますlistcase
。空のリストg
が適用される場合、それ以外の場合は、の右側のすべてが、およびをそれぞれ含む|||
タイプの値に適用されます。関数が最初に適用されます。これは、を保持しながら述語を適用し、タイプの値を返します。これはに渡され、値に応じて保持するかどうかを決定します。結果を次のように返します(a,[a])
head
tail
h
head
((Bool, head),tail)
(uncurry helper)
head
Bool
Either
選択方法を適用できるように値を設定します(|||)
。この値は次の選択肢に渡されます。つまり、保持されて(j ||| (filterA p))
いる述語が、とを含むペアに適用されるようにします。に適用されている間、を使用してフィルタリングされます。両方の結果がペアとして返されます。次に、このペアはlikeを使用して調整されます。それ以外の場合は、が単独で渡されます。True
j
head
tail
head
id
filter p
tail
arr (uncurry (:))
map
tail
filterA p
私がそれを実現するのと同じくらい難しいとは思えませんが、私はかなり明白な何かを見逃していると思います。