Scala でなにか書くつもりだったのに、気づいたら Haskell で Unlambda を書いていた

あ、これを Scala に移植してみればいいのか。

とりあえず、.x, r, s, k, i だけ。d とか c はどうすればいいのかなぁ。

import Data.Char (isSpace)

data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Show
data Func = Func (Func -> IO Func)

apply :: Func -> Func -> IO Func
apply (Func f) g = f g >>= return

p :: Char -> Func
p c = Func (\f -> putChar c >> return f)

r :: Func
r = Func (\f -> putChar '\n' >> return f)

s, k, i :: Func
s = Func (\f ->
          return $ Func (\g ->
                         return $ Func (\h -> do i <- apply f h
                                                 j <- apply g h
                                                 apply i j)))
k = Func (\f -> return $ Func (\g -> return f))
i = Func (\f -> return f)


parse :: String -> Tree Func
parse s = case parse' s of
            Just (t, []) -> t
            Just (t, rest)
                | all isSpace rest -> t
            _ -> error "parse error"

parse' :: String -> Maybe (Tree Func, String)
parse' ('`':cs) =
    do (l, cs')  <- parse' cs
       (r, cs'') <- parse' cs'
       Just (Branch l r, cs'')
parse' ('.':c:cs) = Just (Leaf (p c), cs)
parse' ('r':cs) = Just (Leaf r, cs)
parse' ('s':cs) = Just (Leaf s, cs)
parse' ('k':cs) = Just (Leaf k, cs)
parse' ('i':cs) = Just (Leaf i, cs)
parse' (c:cs)
    | isSpace c = parse' cs
parse' _        = Nothing

eval :: Tree Func -> IO Func
eval (Leaf f) = return f
eval (Branch l r) = do f <- eval l
                       g <- eval r
                       apply f g

http://hw001.gate01.com/eggplant/tcf/unlambda/tutorial.html翻訳:プログラミング言語Unlambda を参考にさせてもらいました。他は特に見てないので、ぐぐってみればもっとかっこいい書き方があるに違いない。Haskell で Unlambda なんて、やってる人はごまんといるよなぁ、多分。

実行例

*Main> eval $ parse "`r`````````````.H.e.l.l.o.,. .w.o.r.l.d.!.a"
Hello, world!
*Main> eval $ parse "```s``si`k.*`ki```s``s`k``s`ksk``sii``si`k``s``s`kski``s``s`ksk``s``s`kski"
************************************(中略)****Main> 

Func はひょっとしてモナドにできたりしないかなぁ。s 書いててヤになってきたので。