3

私はいくつかの入門的な Haskell 資料に取り組んでおり、現在モナドを検討しています。>>=演算子が次のタイプであることを概念的に理解しています。

(Monad m) => m a -> (a -> m b) -> m b.

そのコンテキストでは、次のコードが機能する理由、つまり型の不一致が発生しない理由について混乱しています。

main = getLine >>= \xs -> putStrLn xs

がわかっているのでgetLine :: IO String、 type の関数で「バインド」できると思いString -> IO Stringます。ただしputStrLn、タイプは異なります: putStrLn :: String -> IO ().

では、なぜ Haskell は>>=これら 2 つの関数を使用できるようにしているのでしょうか?

4

3 に答える 3

14

タイプを並べてみましょう。

(>>=)    ::  m      a -> (     a ->  m  b) -> m b
getLine  :: IO String
putStrLn ::              (String -> IO ())

ここにm = IOa = String、およびb = ()があるので、これらを の型シグネチャに代入>>=して、最終的な型シグネチャを取得できます。

(>>=) :: IO String -> (String -> IO ()) -> IO ()
于 2014-10-14T16:39:02.790 に答える
5

()は有効な型 (unit と呼ばれます。底値以外の可能な値を 1 つだけ含むことに注意してください) であり、定義では になりますb

a=Stringおよびb=()したがって、次のようになります。

IO String -> (String -> IO ()) -> IO ()

于 2014-10-14T16:34:40.703 に答える
4

がわかっているのでgetLine :: IO String、 type の関数で「バインド」できると思いString -> IO Stringます。

どうしてそんなことを考えるのか?型シグネチャをもう一度見てください。

(>>=) :: m a -> (a -> m b) -> m b

m aのものは 、右のものは ですm b。特に、真ん中のビット は、a -> m b渡す関数が を>>=受け取り、aを返すことを示していますm b。を返さなければならないとは言っていm aませm bb。一致する必要はありませんa

あなたの例では、ラムダ関数は を取り、Stringを返しますIO ()。そうa = Stringそしてb = ()。そして、それは結構です。

于 2014-10-14T16:46:00.653 に答える