1
module Main (main) where

import Control.Monad.Reader

p1 :: String -> IO ()
p1 = putStrLn . ("Apple "++)

p2 :: String -> IO ()
p2 = putStrLn . ("Pear "++)

main :: IO ()
main = do
    p1 "x"
    p2 "y"
    r "z"

r :: String -> IO ()
r = do
    p1
    p2

それは印刷します:

りんご×梨y梨z

なんで?

4

4 に答える 4

2

rあなたが使用(->) String (IO ()) したのは、typeMonad ((->) String)の値を返すIO ()です。

ReaderTaまたはモナド変換子を使用していません。別のモナドを返すモナドを使用しました。誤ってコンパイルして実行し、ほとんど期待どおりに動作しました。

runReaderTand lift(or ) を使用して、作成しようとしていると思われるものliftIOを達成する必要があります。r

于 2012-12-14T13:20:31.767 に答える
2

まず本体を書き換えましょう

r :: String -> IO ()
r = do
    p1
    p2

を使用して(>>)

r = p1 >> p2

soには、 someのp1タイプが必要であり、 same のタイプが必要です。m aMonad mp2m bm

今、

p1, p2 :: String -> IO ()

その中の最上位の型コンストラクターは関数 arrow(->)です。したがって、Monad使用さrれる

(->) String

[別名リーダーモナド]のMonadインスタンスは、(->) e

instance Monad ((->) e) where
    -- return :: a -> (e -> a)
    return = const
    -- (>>=) :: (e -> a) -> (a -> (e -> b)) -> (e -> b)
    f >>= g = \x -> g (f x) x

その結果、

p1 >> p2 = p1 >>= \_ -> p2
         = \x -> (\_ -> p2) (p1 x) x   -- apply (\_ -> p2) to (p1 x)
         = \x -> p2 x                  -- eta-reduce
         = p2

複雑な書き方でした

r = p2
于 2012-12-14T13:11:41.223 に答える
0

r で p1 と p2 を呼び出すときに、引数を省略しました。あなたが書いたものはポイントフリー表記として解釈されるので、2 番目の IO アクションだけが引数を取得します。これは機能します:

r :: String -> IO ()
r x = do
    p1 x
    p2 x

なぜこれが起こっているのかを理解するには、最初に書いたものが以下と同等であると考えてください。

r = p1 >> p2

コンパイラはそれを次のように解釈します

r x = (p1 >> p2) x

これはあなたが望むものではありません。

于 2012-12-14T13:07:25.123 に答える