http://www.sampou.org/haskell/tutorial-j/io.html
を見ると、
getll = do
c <-getChar
if c=='\n'
then return []
else do
l <- getll
return (c:l)
これが、Hasklell の getline 。(c:l) はリストのcons ね。動くんですが、
indent を間違えると動きません
getll = do c <-getChar と書くとアウトらしい。しかも、これは、Haskell の version 依存があるみたい。まぁ、それは許すんだが...
Pureな関数型言語なのに getChar なんて許されるのかよ
ってのは、そうなんだけど、それが許されるのが Monad 。全然、関数型言語のプログラムに見えないところが良いらしい。
Prelude> :t getChar
getChar :: IO Char
ということなので、Haskell の top level が IO を補っているらしいです。
getChar >>= putChar
とかも可能。
getChar >>= \x -> return x
と lambda 式で受けることもできる。
* * * *
でも、使い方じゃなくて「作り方」の方に興味があるんですが、これが、ぜんぜんわからない。
http://d.hatena.ne.jp/kazu-yamamoto/20110413/1302683869
を見ると、
data Identity a = Identity a deriving Show
instance Monad Identity where
return x = Identity x
(Identity x) >>= f = f x
を
> Identity 1 >>= \x -> return (x + 1)
Identity 2
と使うと書いてある。これは、
run1 y = do
x <- Identity y
return (x + 1)
こう書いても良いらしい。
*Main> run1 3
Identity 4
動くみたい。いや、これが、一体なんなのかが良くわからないんだけどさ。
* * * *
それで、getChar の実装を探してみたんですが、
http://hackage.haskell.org/packages/archive/IOSpec/0.1/doc/html/src/Test-IOSpec-Teletype.html
かなぁ。もちろん、実際のコードではなくて、サンプル実装みたいな感じらしい。これを見ながら、
data SignalState a =
GetChar (Char -> SignalState a)
| ReturnTeletype a
instance Functor SignalState where
fmap f (GetChar tt) = GetChar (\x -> fmap f (tt x))
fmap f (ReturnTeletype x) = ReturnTeletype (f x)
instance Monad SignalState where
return = ReturnTeletype
(ReturnTeletype a) >>= g = g a
(GetChar f) >>= g = GetChar (\c -> f c >>= g)
runTT (ReturnTeletype a) cs = Finish a
runTT (GetChar f) (h:t) = runTT (f h) (t)
data Output a =
Print Char (Output a)
| Finish a deriving Show
getChar1 = GetChar ReturnTeletype
run0 = runTT getChar1 "test"
と直してみると、
*Main> run0
Finish 't'
なんか、動いているっぽい。
getll = do
c <-getChar1
if c=='\n'
then return []
else do
l <- getll
return (c:l)
runn = runTT getll "test\n"
runn1 = runTT getll "test\ntest\n"
で、それっぽく動いているようです。runTT が top level で、"test\n" とかを SignalState に隠して、実行しているわけね。
*Main> runn1
Finish "test"
Finish が付くのが謎だが。まぁ、良い。つうか、どう実行されているのか追うことが難しいんですけど。
いや、でも書きたいものは、また、少し別なんだけど…
No comments:
Post a Comment