、私がしたいのですがカップルのポイントがあります
instance Applicative (Either e) where
pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r
あなたは、これは「短期であることがわかります回路化 ' - Left
に達するとすぐに、それは中止され、そのLeftを返します。これは、貧しい人の厳密さの分析で確認できます。
ghci> (++) <$> Left "Hello" <*> undefined
Left "Hello" -- <<== it's not undefined :) !!
ghci> (++) <$> Right "Hello" <*> undefined
*** Exception: Prelude.undefined -- <<== undefined ... :(
ghci> Left "oops" <*> undefined <*> undefined
Left "oops" -- <<== :)
ghci> Right (++) <*> undefined <*> undefined
*** Exception: Prelude.undefined -- <<== :(
次に、あなたの例は若干トリッキーです。一般的には、関数の型とe
はEither e
には関係ありません。ここで<*>
の型です:私たちが行った場合
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
置換f
- >>Either e
、我々が得る:
(<*>) :: Either e (a -> b) -> Either e a -> Either e b
があなたの例では、
e
と
a
試合は、一般的に彼らはしませんつまり、
Either e
のApplicativeインスタンスをポリモーフィックに実装することはできません。このインスタンスは、左の引数に関数を適用します。
これは伝統的な使い方です。右は興味のある値を表し、左は失敗を表します。 ApplicativeとFunctorを使用して右(正しい)値を結合したり変更することができますが、残った値を残しておくと頑丈に保持されるため、単純なコンパイラの場合と同様に最初のエラーを報告するのに適しています。 – AndrewC