WrappedArrow
是
Applicative
,但它能成为
Monad
(如果箭头是
ArrowApply
)?
我会把
暂且不谈,考虑一个微妙的不同问题:“我们能否成功实施?”
instance ArrowApply y => Monad (y r)
?这个问题的答案是“是”。证明这一点的一种方法是
ArrowMonad
新类型chi提到。。。
newtype ArrowMonad a b = ArrowMonad (a () b)
…和以下同构(参见。
this cstheory.SE question
第18页,共18页
Idioms are oblivious, arrows are meticulous, monads are promiscuous
):
kleislify :: ArrowApply y => y r a -> (r -> y () a)
kleislify af = \r -> arr (const r) >>> af
unkleislify :: ArrowApply y => (r -> y () a) -> y r a
unkleislify f = arr f &&& arr (const ()) >>> app
-- unkleislify . kleislify = kleislify . unkleislify = id
阿罗莫纳德
给我们一个monad实例,我们可以使用
kleislify
-使用箭头并为结果函数提供一个公共参数(换句话说,我们使用
阿罗莫纳德
通过函数的应用程序实例绑定):
bindY :: ArrowApply y => y r a -> (a -> y r b) -> y r b
bindY af h = unkleislify $ (\(ArrowMonad am) -> am) . (\r ->
ArrowMonad (kleislify af r) >>= \x -> ArrowMonad (kleislify (h x) r))
相关
return
也是
阿罗莫纳德
一个,在适当的样板层中:
returnY :: ArrowApply y => a -> y r a
returnY x = unkleislify $ \r -> (\(ArrowMonad am) -> am) (return x)
然而,这并不能回答你的问题。为了实现这一点,
bindY
和
returnY
实用的
实例
拉佩达罗
; 也就是说,我们应该
returnY x = arr (const x)
,以及
ap
我们可以用
宾迪
和
返回
应等同于
(<*>)
WrappedMonad
例如,我们可以尝试使用相关
阿罗莫纳德
实例。。。
instance Arrow a => Applicative (ArrowMonad a) where
pure x = ArrowMonad (arr (const x))
ArrowMonad f <*> ArrowMonad x = ArrowMonad (f &&& x >>> arr (uncurry id))
instance ArrowApply a => Monad (ArrowMonad a) where
ArrowMonad m >>= f = ArrowMonad $
m >>> arr (\x -> let ArrowMonad h = f x in (h, ())) >>> app
…扩展(然后希望简化)
返回
:
returnY
unkleislify $ \r -> (\(ArrowMonad am) -> am) (return x)
unkleislify $ \r -> (\(ArrowMonad am) -> am) (ArrowMonad (arr (const x)))
unkleislify $ \r -> arr (const x)
arr (\r -> arr (const x)) &&& arr (const ()) >>> app
arr (const (arr (const x))) &&& arr (const ()) >>> app
arr (\r -> (r, r)) >>> arr (const (arr (const x))) *** arr (const ()) >>> app
arr (\r -> (arr (const x), ())) >>> app
arr (const x)
任何
箭头应用
也许能够翻转箭头(如Alec和user2407038所建议的)将有助于摆脱
()
Kleisli
arr (\r -> (arr (const x), ())) >>> app
Kleisli (\r -> return (arr (const x), ())) >>> Kleisli (\(Kleisli f, x) -> f x)
Kleisli ((\r -> return (arr (const x), ())) >=> (\(Kleisli f, x) -> f x))
Kleisli ((\r -> return (Kleisli (return . const x), ()))
>=> (\(Kleisli f, x) -> f x))
Kleisli (\r -> return (Kleisli (return . const x), ())
>>= (\(Kleisli f, x) -> f x))
Kleisli (\r -> (\(Kleisli f, x) -> f x) (Kleisli (return . const x), ()))
Kleisli (\r -> (return . const x) ())
Kleisli (\r -> return x)
Kleisli (return . const x)
arr (const x)
我还没有尝试过这样做
宾迪
,但我不知情的猜测是,会出现类似的情况。