2017-07-17 16 views
4

を流し:Applicativeの状態のインスタンス - データの順序は、私は、このようなタイプのためのApplicativeのインスタンスを実装しようとしています

newtype State s a = State {runState :: s -> (a, s)} 

私は(< *>)機能のためのいくつかのさまざまなアイデアを持っています。私の心に来る、それを実装する 一つの方法は、

1(またはそれらのんでも任意の)
(<*>) :: State s (a -> b) -> State s a -> State s b 
State f <*> State s = State $ do 
    (fa, fs) <- f 
    let (sa, ss) = s fs 
    return (fa sa, ss) 

それとも

(<*>) :: State s (a -> b) -> State s a -> State s b 
State f <*> State s = State $ do 
    (sa, ss) <- s 
    let (fa, fs) = f ss 
    return (fa sa, fs) 

は正しいと理由ですか?

これらは両方とも型チェックであり、「状態」変換の順序によってのみ異なります。私は別のものより1つを好む良い理由を見つけることができません...

+1

この質問は、[nerd snipe](https://xkcd.com/356/)の熟した機会のようです。 'State =' = g = State $ \ s - > let {(u、x)}を考えるための 'State'のようなモナドのための' = ft; (t、y)= runState(g x)s}を(u、y) 'とする。どのように 'x'、' y'が上から下にいくのかを観察するが、 's'、' t'、 'u'は下から上に行く。まだ私の脳を傷つける:) –

+1

あなたがそれを見たことがないなら、[これは好きかもしれません](https://lukepalmer.wordpress.com/2008/08/10/mindfuck-the-reverse-state-monad/) – luqui

+0

@BenjaminHodgsonそれは奇妙に奇妙です – 4castle

答えて

4

私が見る限り、適用法に違反しないため、両方とも正しいと確信しています。しかし、最初は実際に使用されるものです。私はこれが慣例のためだと思う:<*>の左手の議論の影響が最初の右の議論の前に適用されることが期待される。

(,) <$> readLn <*> getLine :: IO (Int, String) 

は文字列を読み出し、最初のIntのために求められ、そしてここで、例えば、IOと比較します。状態を同様の方法で動作させることは良いことです。

+3

「Monad」インスタンスが与えられていると仮定して、これは完全に真ではないと思います「状態」のために。 'f'が' Monad'でもあるならば、 '' Applicative''法の状態(https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Applicative.html#t:Applicative) '(<*>)= ap'を満たしていなければなりません。最初の定義は、通常の' Monad'インスタンスを仮定して違反します。 –

4

どちらも妥当です。あなたが他の1からそれらのいずれかを得ることができることに注意してください:

x <*2> y = flip ($) <$> y <*1> x 

それは「効果は」左から右に実行されていること、しかし、ライブラリの慣例です。したがって、最初のバージョンはもっとよく知られています。

4

まずは、(モナド!)doのようなアプリケーションインスタンスを定義するための構文を使用しないことをお勧めします。なぜなら、何が起こっているのかをあいまいにするからです。ここだけの標準的な機能の構文を使用して、あなたの定義です:

State f <*> State s = State $ \q 
    -> let (fa, fs) = f q 
      (sa, ss) = s fs 
     in (fa sa, ss) 

State f <*> State s = State $ \q 
    -> let (fa, fs) = f ss 
      (sa, ss) = s q 
     in (fa sa, fs) 

また、これは(モナドのインスタンスとは異なり)Applicativeのインスタンス内の任意の固有の評価順序は、実際にそこではないということ、それがより明確になります。

+0

チップありがとう!私はこの記法を過度に使用しないようにします。 – Ikciwor

+2

@IKciworこの表記を一般的に使用する際には何も問題ありません。アドバイスは依存関係に依存しているため、ここでは使用しないようにしています.MonadはApplicativeの上に構築されたより強力な機能です。したがって、モナド表記を使用して '<*> 'を定義することは、循環依存性と同様です。もちろん、実際には両方が存在することがわかっている場合はどちらの順番でも定義できますが、動作の仕方を理解しようとするときには、最小から最大の順に構築する方が良いでしょう。 – amalloy

+1

正確には、それは私が意味することです - モナドは厳密に適用よりも特別です。これは本当に重要ではありません。なぜなら、 'do'はあなたが定義しているモナドとは全く異なるモナド(関数/リーダモナド)を実際に使用しているからです。明示的なラムダなどで書かれていてもよいので、私はそのモナドをかなり一般的に避けています。 – leftaroundabout

関連する問題