WrappedArrow
はApplicative
のインスタンスであるが、それはおそらくMonad
(あれば行うことができます矢印はArrowApply
です)?
私は一瞬脇WrappedArrow
を入れて、微妙に異なる問題を検討します「我々は成功しinstance ArrowApply y => Monad (y r)
を実装することはできますか?」。この質問に対する答えは「はい」です。
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
ArrowMonad
は私達を与える:それを証明する一つの方法は、ArrowMonad
のnewtypeカイは...
newtype ArrowMonad a b = ArrowMonad (a() b)
に言及...と、次の同型(参照this cstheory.SE questionとIdioms are oblivious, arrows are meticulous, monads are promiscuousの18ページ)に依存しています
01:我々は矢印-ing、得られた機能(換言すれば、我々は関数のApplicativeのインスタンスを通して
ArrowMonad
バインドを使用している)に共通の引数を供給
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
も定型の適切な層で表現ArrowMonad
1、次のとおりです。
returnY :: ArrowApply y => a -> y r a
returnY x = unkleislify $ \r -> (\(ArrowMonad am) -> am) (return x)
これは、しかし、あなたの質問に答えていません。それが起こるためには、bindY
とreturnY
はWrappedArrow
のApplicative
インスタンスと一致しなければなりません。つまり、我々はreturnY x = arr (const x)
を持つべき、と私たちはbindY
とreturnY
で書くことができますap
はWrappedMonad
ため(<*>)
と同等でなければなりません。例えば、我々はreturnY
拡大(その後、うまくいけば簡素化)するために...関連ArrowMonad
インスタンス...
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
私はそれかどうかはわかりません任意のArrowApply
に対してarr (const x)
に単純化することができます。おそらく矢印を反転することができる(Alecとuser2407038が示唆しているように)()
を取り除くのに役立つだろうが、私はそれを解決していない。私はbindY
と同じことをやってしようとしていませんが、私の無知の推測では、同様のシナリオがもたらすことである
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)
:いずれの場合では、Kleisli
ために、少なくとも我々は上で運ぶことができます。
たぶん、あなたは[ 'Control.Arrow.ArrowMonad'](https://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Arrow.html#t:ArrowMonad)をしたいですか? 'b'が'() 'でなければ、賢明なモナドのインスタンスを定義するのは難しいでしょう。 – chi
このようなインスタンスを定義するには、さらに関数swap :: forall x y zが必要です。 arr x(arr y z) - > arr y(arr x z) '; '>> = = \ x f - > swap(arr f)&&& x >>> app'となります。このような関数を 'base'の' Arrow'インスタンスに定義するのはかなり簡単ですが、一般的にどのように役立つかは言えません。あなたの編集について – user2407038
:あなたはおそらくすでに( ''文字通りであることが、どのような場合には、それはあなたの代わりに 'アクション1> =>アクション2> => action3'を書くかもしれないと言及する価値がある('(> =>)を知っている>>> ) 'のために)。 – duplode