2016-07-02 8 views
4

私はHaskellの初心者です。エラー処理のためにEitherを使用するいくつかのHaskellコードに取り組んでいます。 Eitherの左の要素はエラーを表し、右の要素は正常な結果を表します。コードでは、このユースケース用に設計されているような、Applitherative of Eitherを使用することがよくあります。Eithersのリストをリストに変換する

タイプ[Either e r]のオブジェクトが与えられた場合、それをタイプEither e [r]のオブジェクトに変換する最もエレガントな方法は何ですか?これは、呼び出された関数からの戻り値の配列を持つ可能性があり、それらの戻り値のいずれかがエラーであれば、そのエラーを取得して他のものをすべて破棄したいと考えています。配列の複数の要素にエラーがある場合は、できるだけ一番左のエラーを取得することをお勧めします。

次のコードでは、2つの関数を記述することでこの問題を解決できましたが、そのうちの1つは再帰的ですが、より良い方法がありますか? Control.Monadから

type Error = [Char] 

myFunc :: [Either Error a] -> Either Error [a] 
myFunc = myFunc2 [] 

myFunc2 :: [a] -> [Either Error a] -> Either Error [a] 
myFunc2 r ((Left error):rest) = Left error 
myFunc2 r ((Right item):rest) = myFunc2 (r ++ [item]) rest 
myFunc2 r [] = Right r 

main :: IO() 
main = do 
    -- This prints: Right [1, 2, 3] 
    putStrLn (show (myFunc [Right 1, Right 2, Right 3])) 

    -- This prints: Left "division by zero" 
    putStrLn (show (myFunc [Right 1, Left "division by zero", Right 3])) 
+1

sequenceAあなたはと呼ばれる便利なサイトがあります、それを認識していませんよ[Hoogle](https://www.haskell.org/hoogle/)ここでタイプを入力できますあなたが見たいと思っている関数のシグネチャと一致/類似のシグネチャを持つ関数の提案を与えるでしょう。悲しいことに、[[lr]]→[l [r] 'は結果をもたらしていないようです:( – paul

答えて

12

sequence

sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) 

のように:

\> import Control.Monad (sequence) 

\> sequence [Right 1, Right 2, Right 3] 
Right [1,2,3] 

\> sequence [Right 1, Left "division by zero", Right 3] 
Left "division by zero" 
+0

ありがとう、それはうまくいきます!私はちょうど初心者なので、この回答を受け入れるかどうか、 'sequence'の利点は何ですか? –

+3

@DavidGrayson _default_インプリメンテーションは同じです(ソースコード内の' sequence = sequenceA'を参照)(http://hackage.haskell。 org/package/base-4.9.0.0/docs/src/Data.Traversable.html#Traversable)あなたがモナドではないアプリケーションを持っているなら、 'sequenceA'を使います。 –

+0

@David Grayson彼らは同じことをします。歴史的な理由から、さまざまな機能があります。https://wiki.haskell.org/Functor-Applicative-Monad_Proposal#Redundant_functions – danidiaz

8

利用の場合Data.Traversable

+0

ありがとうございます!私はちょうど初心者ですので、この回答を受け入れるかどうかは分かりませんこれはControl.Monadから 'sequence'を推奨しています。' sequenceA'の利点は何ですか? –

+3

'sequence'と' sequenceA'は 'Either'と同じです。彼らが存在する理由は歴史的です:Functor-Applicativeの前に - Monad Proposal 'Applicativeは' Monad 'のスーパークラスではなく、 'traverse'や' mapM'のように多くの機能が2回実装されました。 – mariop

関連する問題