_ <- 省略できたらいいのになあ #start_scalaz
— Toshiyuki Takahashiさん (@tototoshi) 9月 9, 2012
ScalaでもHaskellのdo記法っぽく書ける。調度良くScalaでHaskellしてる記事があったので、これを参考にさせていただきます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language._ | |
import scala.util.continuations._ | |
import scalaz._, Scalaz._ | |
import effect._, IO._ | |
import scalaz.syntax.Ops | |
object Do { | |
sealed trait DoBindOps[F[_], A] extends Ops[F[A]] { | |
implicit val F: Bind[F] | |
val self: F[A] | |
def bind[B] = shift((k: A => F[B]) => self >>= k) | |
} | |
implicit def ToDoBindOps[F[_]: Bind, A](fa: F[A]) = new DoBindOps[F, A] { | |
val F = implicitly[Bind[F]] | |
val self = fa | |
} | |
def apply[F[_]: Bind, A](fa: => F[A] @cps[F[A]]) = reset(fa) | |
} | |
object Main extends SafeApp { | |
import Do._ | |
override def runc = Do { | |
ch07.basicio.bind[Unit] | |
ch07.callingpure | |
} | |
object ch07 { | |
def basicio = Do { | |
putStrLn("Greetings! What is your name?").bind[Unit] | |
val inpStr = readLn.bind[Unit] | |
putStrLn(s"Welcome to Haskell, $inpStr!") | |
} | |
def callingpure = { | |
def name2reply(name: String) = { | |
val charcount = name.length | |
s"""Pleased to meet you, $name. | |
Your name contains $charcount characters.""" | |
} | |
Do { | |
putStrLn("Greetings once again. What is your name?").bind[Unit] | |
val inpStr = readLn.bind[Unit] | |
val outStr = name2reply(inpStr) | |
putStrLn(outStr) | |
} | |
} | |
} | |
} |
※追記
実践Scalaプログラミング読みなおしてみたらこっちの方が良さそう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language._ | |
import scala.util.continuations._ | |
import scalaz.syntax.bind._ | |
import scalaz.effect._, IO._ | |
class Do[A] { | |
class Bind[B] { | |
def apply[F[_]: scalaz.Bind, A](fa: F[A]) = shift((k: A => F[B]) => fa >>= k) | |
} | |
def apply[F[_]](f: Bind[A] => F[A] @cps[F[A]]) = reset(f(new Bind[A])) | |
} | |
object Do { | |
def apply[A] = new Do[A] | |
} | |
object Main extends SafeApp { | |
override def runc = Do[Unit] { bind => | |
bind(ch07.basicio) | |
ch07.callingpure | |
} | |
object ch07 { | |
def basicio = Do[Unit] { bind => | |
bind(putStrLn("Greetings! What is your name?")) | |
val inpStr = bind(readLn) | |
putStrLn(s"Welcome to Haskell, $inpStr!") | |
} | |
def callingpure = { | |
def name2reply(name: String) = { | |
val charcount = name.length | |
s"""Pleased to meet you, $name. | |
Your name contains $charcount characters.""" | |
} | |
Do[Unit] { bind => | |
bind(putStrLn("Greetings once again. What is your name?")) | |
val inpStr = bind(readLn) | |
val outStr = name2reply(inpStr) | |
putStrLn(outStr) | |
} | |
} | |
} | |
} |
しかし、完全に推論させることは出来なさそう。
for式使いましょう。
0 件のコメント:
コメントを投稿