wvogel日記

自分用の技術備忘録が多めです.

IO

IOは難しい.....
ふつけるでアクションと説明されていて、ふむそういうものなのかと思っていたけれど、そんな特殊なものがHaskellにあるわけないだろう!
と思って記事を。
Haskellでは、すべては関数です。多分。


以前書いた、

import Control.Applicative

print' :: String -> String -> IO ()
print' n = print.sum.map read.take (read n).words

main =print' <$>getLine<*>getContents

の記事の、解決編です。



コメントで指摘をいただき、
main関数の型が、IO (IO ())になっていることがわかりました。


(<$>)の型が、

Prelude Control.Applicative> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b

となっているので、まずはfunctorの型クラスのインスタンスを見てみる。


するとこいつは、
リストモナド
Maybeモナド
IOモナド
インスタンスに持つ。


次に、getLine,getContentsの型を調べる。

getLine :: IO String
getContents :: IO String

なので、これはgetLineに問題がありそうです。

Hoogle情報により

getLine same as hGetLine stdin

とのこと。
そこで、hGetLineを調べてみると、

hGetLine :: Handle -> IO String

この結果をソースコードに起き変えると、(<$>)の型は、

(<$>) :: Functor f => (Handle -> IO String) -> Handle -> IO (IO String)

になってしまうことになるのかな。
関数は全て一引数であることを踏まえると、先にgetLineの型が評価され、それに合わせて第二引数の型が決定されるんだろうから。
つまり、第二引数の型がIO Stringであるはずのところ、Handleになってしまっているので、これはつまりstdin,
よって、実際に動かしても入力を受け付けなかったと考えられる。
どういうことかというと、

getContents :: Handle -> IO Stirng

なので、getContentsが、stdinだけで評価されたということ??
解決編と思いきや、なかなかうまくいかない。
うーん、よくわからなくなってきた


それで、うまく動作しなかったんですね。