2013-11-24 9 views
6

MonopはIOのためのHaskellをどのように使うのかを見ることができます。データフロー操作のための関数を作成する場合と同じように、Monadsを使って「計算をまとめて」使うことができます。モンスターの制御フロー - シーケンス、選択と反復

私が唯一grokkingしているのは、Monads for Control Flowを使用できることです。これで、コントロールフローがシーケンス、選択、反復について理解できるようになりました。今はmap、foldl、filter、zipwith/mapcatのような高次関数を使ってリストを操作するのに慣れています。

私の質問は - 制御フローを達成するためにモナドでシーケンス、選択、反復を行うことができますか? Haskellでは配列決定のため

答えて

5

(ハスケル、スカラ座やClojureの中に答えをハッピー) 、あなたは機能を持っている>>=sequence

(>>=) :: Monad m => m a -> (a -> m b) -> m b 
sequence :: Monad m => [m a] -> m [a] 

>>=またはバインド機能は、モナド行動をとる値を抽出し、それを新しいモナドのアクションを返す関数に送ります。 sequence関数は、同じ型のモナドのアクションのリストを取り、それらのすべてを実行し、結果を集約し、単一のアクションとしてラップします。反復のため

お持ちmapMforMforM = flip mapM

mapM :: Monad m => (a -> m b) -> [a] -> m [b] 

mapMforM機能は、リストの各要素に対してアクションを返す関数を適用する単一のアクションとして結果を集約するためのものです。

選択のために、私はあなたが条件式を意味するものと仮定します。これはHaskellでif-the-else式として実装されています。それらは、純粋な表現で使用できるものと同じモナド式で直接使用することができます。しかし、特定のモナドを使用して選択肢を実行したり、少なくともエラーを処理したりすることもできます。それは非常に単純な実装を持っている

data Maybe a = Nothing | Just a 

instance Monad Maybe where 
    return a = Just a 
    (Just a) >>= f = f a 
    Nothing >>= f = Nothing 

:完全に理解するのが最も簡単でMaybeモナドです。基本的に、Nothingを他のものにシーケンスすると、毎回Nothingが返されます。これは、あなた短絡故障の概念を与える:

ここ
lookup :: Eq a => a -> [(a, b)] -> Maybe b 
-- Looks up a value in a key-value association list 

myFunc :: Int -> [(String, Int)] -> Maybe Int 
myFunc mult assocList = do 
    i <- lookup "foo" assocList 
    j <- lookup "bar" assocList 
    return $ i * mult + j 

"foo"のルックアップが失敗した場合、myFuncはすぐNothingを返します。同様に、"bar"の検索が失敗した場合、myFuncはすぐにNothingを返します。両方のルックアップが成功した場合にのみ、myFuncは計算を行います。これは、ある種の「エラー処理」を提供します。 「失敗」値は、このような文字列のエラーメッセージまたは障害が発生した時点での計算の状態として、いくつかのコンテキストを運ぶことができ除いて、非常に同じように動作します似たモナドEither a

data Either a b = Left a | Right b 

instance Monad (Either a) where 
    return a = Right a 
    (Right a) >>= f = f a 
    (Left a) >>= f = Left a 

があります。

+1

'' = 'は本当にシーケンスを保証するのですか、それとも最も一般的なモナドの動作ですか? – kqr

+1

@kqrあなたが求めているのであれば、評価の順序付けを保証するものではありません。なぜなら、評価の順序は '(>> =)'の定義に依存し、 '(>> =)'のすべての実装が第2引数の前に第1引数を評価するわけではないからです。 –

+0

@kqr順序を保証するものではありませんが、do not表記を使用することができる関数です。これは、質問として解釈したものです。 bindは本質的にdo文の各アクションの(暗黙の)セミコロンを定義するので、特定のコードブロックの制御フローの側面を定義する方法を提供します。 – bheklilr

関連する問題