2013-04-13 7 views
5

Возьмите этот простой бит кода:Простой поток управления в scalaz эффект

var line = ""; 

do { 
    println("Please enter a non-empty line: ") 
    line = readLine() 
} while (line.isEmpty()) 

println("You entered a non-empty line: " + line) 

Это, безусловно, не особенно элегантно, особенно в связи с неудачным обзорного из line - однако, я думаю, что это довольно просто читать.

Теперь пытается перевести это непосредственно scalaz эффект, я придумал:

def nonEmptyLine: IO[String] = for { 
    _ <- putStrLn("Please enter a non-empty line:") 
    line <- readLn 
    r <- if (line.isEmpty()) nonEmptyLine else IO(line) 
} yield r 


(for { 
    line <- nonEmptyLine 
    _ <- putStrLn("You entered a non-empty line: " + line) 
} yield()).unsafePerformIO 

Что заставляет меня чувствовать, что я что-то не хватает, так как это не чувствует, как улучшение вообще? Есть ли какой-то элемент управления потоком более высокого порядка, который мне не хватает?

ответ

3

Вы можете сделать это (по крайней мере, возможно) намного симпатичнее, пропуская for обозначения и используя комбинаторы *> и >>= в трубе все вместе:

import scalaz._, Scalaz._, effect._, IO._ 

val prompt = putStrLn("Please enter a non-empty line:") 

def report(line: String) = putStrLn("You entered a non-empty line: " + line) 

def nonEmptyLine: IO[String] = prompt *> readLn >>= (
    (line: String) => if (line.isEmpty) nonEmptyLine else line.point[IO] 
) 

А потом:

scala> (nonEmptyLine >>= report).unsafePerformIO 
Please enter a non-empty line: 
You entered a non-empty line: This is a test. 

В целом, однако, я не уверен, что вам следует ожидать, что код, написанный с использованием scalaz.effect, будет более кратким или более простым для чтения, чем простое императивное решение.