为什么这个函数不会立即失效?
Why does this function not fail immediately?
我有以下一段代码。 main
获取 stdin
文本并通过 g
对它进行排序,之后 f
打印它的输出和 returns 一个适当的 ExitCode
被提交使用 exitWith
.
我的问题是,为什么这个程序在 运行 输入样本时,在输入第一行 (test
) 后没有立即终止,而是在读取第二行后才失败(test2
)?我想要发生的是 g
函数在 parse1
returns Left "left: test"
之后立即 return 而不是等到输入第二行。
代码:
import System.Exit
import Control.Monad
import Data.Either
type ErrType = String
parse1 :: String -> Either ErrType Int
parse1 "test" = Left "left: test"
parse1 _ = Left "left"
parse2 :: String -> Either ErrType Char
parse2 s = Right (head s)
g :: String -> Either String String
g str =
let l1:l2:ls = lines str
in either (Left . show) (Right . show) $ do
a <- parse1 l1
b <- parse2 l2
return "placeholder"
main = getContents >>= f.g >>= exitWith
where f (Right s) = putStrLn s >> return ExitSuccess
f (Left s) = putStrLn s >> return (ExitFailure 1)
标准输入流:
test
test2
行
let l1:l2:ls = lines str
意味着即使只是 l1
, 整个 模式 l1:l2:ls
也需要匹配,这意味着需要进行检查 str
实际上至少包含两行。使用惰性输入,这会导致您看到的行为。
您可以使用延迟第二行检查的显式惰性模式来修复它:
let l1 : ~(l2:ls) = lines str
或者,由于 let 中的顶级模式是隐式惰性的,您可以将其拆分为:
let l1:ls' = lines str
l2:ls = ls'
我有以下一段代码。 main
获取 stdin
文本并通过 g
对它进行排序,之后 f
打印它的输出和 returns 一个适当的 ExitCode
被提交使用 exitWith
.
我的问题是,为什么这个程序在 运行 输入样本时,在输入第一行 (test
) 后没有立即终止,而是在读取第二行后才失败(test2
)?我想要发生的是 g
函数在 parse1
returns Left "left: test"
之后立即 return 而不是等到输入第二行。
代码:
import System.Exit
import Control.Monad
import Data.Either
type ErrType = String
parse1 :: String -> Either ErrType Int
parse1 "test" = Left "left: test"
parse1 _ = Left "left"
parse2 :: String -> Either ErrType Char
parse2 s = Right (head s)
g :: String -> Either String String
g str =
let l1:l2:ls = lines str
in either (Left . show) (Right . show) $ do
a <- parse1 l1
b <- parse2 l2
return "placeholder"
main = getContents >>= f.g >>= exitWith
where f (Right s) = putStrLn s >> return ExitSuccess
f (Left s) = putStrLn s >> return (ExitFailure 1)
标准输入流:
test
test2
行
let l1:l2:ls = lines str
意味着即使只是 l1
, 整个 模式 l1:l2:ls
也需要匹配,这意味着需要进行检查 str
实际上至少包含两行。使用惰性输入,这会导致您看到的行为。
您可以使用延迟第二行检查的显式惰性模式来修复它:
let l1 : ~(l2:ls) = lines str
或者,由于 let 中的顶级模式是隐式惰性的,您可以将其拆分为:
let l1:ls' = lines str
l2:ls = ls'