2016-11-11 8 views
2

WrappedArrowApplicativeのインスタンスですが、Monad(おそらく矢印がArrowApplyの場合)にすることはできますか?WrappedArrowのMonadインスタンスを定義できますか?

instance ArrowApply a => Monad (WrappedArrow a b) where 
    return = pure 
    (>>) = (*>) 
    (>>=) = ??? 

EDIT:

は私の当初の目的は、(ラップ)Kleisliのためのモナドのインスタンスを持っていることだったので、私は

runWithInput input $ do 
    action1 
    action2 
    action3 
    ... 

代わりの

do 
    output1 <- action1 input 
    output2 <- action2 output1 
    output3 <- action3 output2 
    ... 

しかし、私を書くことができ望ましい意味を持たないことに気づいた。 newtypesの剥奪、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) 

は、だから私は、私はStateTまたはカスタムを使用する必要がありますと仮定しますdoでこのようにアクションをシーケンスしたい場合はモナドを使用してください。

+0

たぶん、あなたは[ 'Control.Arrow.ArrowMonad'](https://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Arrow.html#t:ArrowMonad)をしたいですか? 'b'が'() 'でなければ、賢明なモナドのインスタンスを定義するのは難しいでしょう。 – chi

+0

このようなインスタンスを定義するには、さらに関数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

:あなたはおそらくすでに( ''文字通りであることが、どのような場合には、それはあなたの代わりに 'アクション1> =>アクション2> => action3'を書くかもしれないと言及する価値がある('(> =>)を知っている>>> ) 'のために)。 – duplode

答えて

3

これはXYの問題ですので、私はあなたが尋ねた質問の両方にお答えします、とあなたはおそらく聞きしたかった質問:

WrappedArrowApplicativeのインスタンスであるが、それはMonad行うことができます(おそらく矢印がArrowApplyの場合)?

はい、可能ですが、もっと制約が必要です。実際、これを行うにはいくつかの方法があると思います。あなたは(->)ために、そのインスタンスを経由してArrowSwapのためのいくつかの直感を得ることができます

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 

:たとえば、あなたがuser2407038 @によって提案されたアプローチを取ることができる。もちろん、

instance ArrowSwap (->) where 
    swap :: (b -> (c -> d)) -> c -> b -> d 
    swap = flip 

、そのすぐに明確ではありませんこれは便利です...

私の当初の目的は、私は

0を書くことができる(ラップ)Kleisli、 のためのモナドのインスタンスを持っていることでした
runWithInput input $ do 
    action1 
    action2 
    action3 
    ... 

代わりの

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 
+0

* base *に似た関数があれば、 'ArrowFlip'と' flip'は間違いなくもっと透明な名前になります。 – duplode

+0

@duplode私は完全に同意します!私は当初、それを書いていましたが、私のサンプルインスタンスでは、Preludeをインポートして、修飾された 'flip 'を使用しなければならないということを意味していました。私はそれがそれに値するものではないかもしれないと思った。 :) – Alec

+0

それは本当に迷惑になるでしょう。実際には、私はこの質問で遊んでいる間に、ある時点でGHCiで 'fleep'関数を定義していたことを一時的に忘れていました:) – duplode

1

WrappedArrowApplicativeのインスタンスであるが、それはおそらく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 questionIdioms 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) 

これは、しかし、あなたの質問に答えていません。それが起こるためには、bindYreturnYWrappedArrowApplicativeインスタンスと一致しなければなりません。つまり、我々はreturnY x = arr (const x)を持つべき、と私たちはbindYreturnYで書くことができますapWrappedMonadため(<*>)と同等でなければなりません。例えば、我々は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ために、少なくとも我々は上で運ぶことができます。

+0

私は昨晩同様のことをしていました。私は 'Monoid'または' Default'制約を追加することを考えました。( ' ) ')。しかし、それが「モナド」法を満足させるものを与えるかどうかはわかりません。私の直感は言っていない...いい説明! – Alec

関連する問題