WrappedArrow
是 Applicative
的一个实例,但它可以成为 Monad
(可能是如果箭头是 ArrowApply
)吗?
instance ArrowApply a => Monad (WrappedArrow a b) where
return = pure
(>>) = (*>)
(>>=) = ???
编辑:
我最初的目的是为(包装的)Kleisli 提供一个 Monad 实例,这样我就可以编写
runWithInput input $ do
action1
action2
action3
...
而不是
do
output1 <- action1 input
output2 <- action2 output1
output3 <- action3 output2
...
但我意识到这没有任何意义。去掉新类型,Kleisli f a b >> Kleisli f a c
是
(a -> f b) -> (a -> f c) -> (a -> f c)
我需要的是 >>>
的模拟,即 b 而不是第二个 a
:
(a -> f b) -> (b -> f c) -> (a -> f c)
所以我想如果我想用 do
以这种方式对操作进行排序,我将不得不使用 StateT
或自定义 monad。
最佳答案
由于这是一个 XY 问题,我将回答您提出的问题以及您可能想问的问题:
WrappedArrow
is an instance ofApplicative
, but can it be made aMonad
(probably if the arrow isArrowApply
)?
是的,可以,但您需要更多限制。事实上,我认为有几种方法可以做到这一点。例如,您可以采用@user2407038建议的方法:
class Arrow a => ArrowSwap a where
swap :: a b (a c d) -> a c (a b d)
instance (ArrowApply a, ArrowSwap a) => Monad (WrappedArrow a b) where
return = pure
WrapArrow m >>= f = WrapArrow $ swap (arr (unwrapArrow . f)) &&& m >>> app
您可以通过 (->)
的实例获得 ArrowSwap
的一些直觉:
instance ArrowSwap (->) where
swap :: (b -> (c -> d)) -> c -> b -> d
swap = flip
当然,目前还不清楚这是否有用......
My initial purpose was to have a Monad instance for (wrapped) Kleisli, so I could write
runWithInput input $ do action1 action2 action3 ...
instead of
do output1 <- action1 input output2 <- action2 output1 output3 <- action3 output2 ...
这就是 RebindableSyntax
用于:
{-# LANGUAGE RebindableSyntax #-}
import Control.Monad (>=>)
action1 :: Monad m => T1 -> m T2
action2 :: Monad m => T2 -> m T3
action3 :: Monad m => T3 -> m T4
action4 :: Monad m => T1 -> m T4
action4 = let (>>) = (>=>) in do
action1
action2
action3
关于haskell - 我们可以为 WrappedArrow 定义一个 Monad 实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40553131/