答えて

0

どのような意味ではIOモナドでCGIモナドを組み合わせることができるようにする必要がありますが、たぶんモナドも良いかもしれないとIOモナドを組み合わせた方法の例モナドを組み合わせる?

f :: Int -> IO (Maybe Int) 
f x = do 
    putStrLn "Hello world!" 
    return $ if x == 0 then Nothing else Just x 

をするために評価することができる:

[1 of 1] Compiling Main    (maybe-io.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> f 0 
Hello world! 
Nothing 
*Main> f 3 
Hello world! 
Just 3 
+3

あなたはMaybe上で計算を構成していないので、Maybeがモナドであるという事実は無関係です。 – jrockway

17

あなたは正確にあなたがIOMaybeを結合する方法を言うことはありませんが、私はあなたが簡単に結合したいIO (Maybe a)を返す多くの機能を持っていると仮定します。基本的にあなたがそれ自身のMonadインスタンスと別の型としてIO (Maybe a)を扱いたい:これにより

newtype IOMaybe a = IOM (IO (Maybe a)) 

-- "unpack" a value of the new type 
runIOMaybe :: IOMaybe a -> IO (Maybe a) 
runIOMaybe (IOM a) = a 

instance Monad IOMaybe where 
    -- bind operator 
    (IOM ioa) >>= f = IOM $ do 
     a <- ioa 
     case a of 
     Nothing -> return Nothing 
     Just v -> runIOMaybe (f v) 

    -- return 
    return a = IOM (return (Just a)) 

-- maybe also some convenience functions 
returnIO :: IO a -> IOMaybe a 
returnIO ioa = IOM $ do 
    v <- ioa 
    return (Just v) 

returnMaybe :: Maybe a -> IOMaybe a 
returnMaybe ma = IOM (return ma) 

あなたがIO (Maybe a)IO aまたはMaybe aを返す関数を組み合わせることdo -Notationを使用することができます。

f1 :: Int -> IO (Maybe Int) 
f1 0 = return Nothing 
f1 a = return (Just a) 

main = runIOMaybe $ do 
    returnIO $ putStrLn "Hello" 
    a <- returnMaybe $ Just 2 
    IOM $ f1 a 
    return() 

一般的に、このようなモナドを組み合わせて変更するものはmonad transformerと呼ばれ、GHCには一般的なケースのモナドトランスを含むpackageが付属しています。あなたのシナリオに合ったこのモナド・トランスフォーマー・ライブラリーに何かがある場合は、MaybeとIOをどのように組み合わせたいかによって決まります。

+0

あなたが気づいていなかった場合は、 'newtype IOMaybe a = IOM {runIOMaybe :: IO(Maybe a)}'を宣言することによって自動的に 'runIOMaybe'を作成することができます。 – rovaughn

21

早起きのためにMaybeモナドを使用することを前提としています(breakまたはreturn、C言語)。

この場合、MaybeTパッケージ(cabal install MaybeT)のMaybeTを使用する必要があります。

main = do 
    runMaybeT . forever $ do 
    liftIO $ putStrLn "I won't stop until you type pretty please" 
    line <- liftIO getLine 
    when ("pretty please" == line) mzero 
    return() 

多分、モナモードのモナドトランスバージョンです。

モナドトランスは、他のモナドに「機能を追加」します。

+3

また、mtlにErrorTがあること、 MonadPlusを実装しています。つまり、上記のコードはErrorモナドではほとんど変わりません。 (変更は、ErrorTの "Left"部分にタイプシグネチャが必要であるということです。 "mzero"はあまり具体的ではありません)。 – jrockway

+0

@jrockway:左のタイプには、エラーのインスタンスが必要です。これは少し不便です'MaybeT'は実際には' ErrorT() 'のような同形ですが、'インスタンスError() 'がないのでこれは許されません。 'EitherT'を使う方が良いでしょうが、これには追加のパッケージも必要です。 –

関連する問題