我有以下代码.main获取stdin文本并对其进行排序g,然后f输出文本的输出并返回使用的提交的相应ExitCode内容exitWith.
我的问题是为什么这个程序在使用示例输入运行时,不会在输入第一行(test)之后立即终止,而只是在读取第二行(test2)之后失败?我想要发生的是g函数在返回后立即parse1返回,Left "left: test"而不是等到输入第二行.
码:
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)
Run Code Online (Sandbox Code Playgroud)
标准输入流:
test
test2
Run Code Online (Sandbox Code Playgroud)
这条线
let l1:l2:ls = lines str
Run Code Online (Sandbox Code Playgroud)
意味着要评估甚至只是l1,整个模式l1:l2:ls需要匹配,这意味着需要进行str实际包含至少两行的检查.使用延迟输入,会导致您看到的行为.
您可以使用显式延迟模式来修复它,该模式会延迟第二行的检查:
let l1 : ~(l2:ls) = lines str
Run Code Online (Sandbox Code Playgroud)
或者,因为let中的顶部模式是隐式延迟的,所以你可以将其拆分为:
let l1:ls' = lines str
l2:ls = ls'
Run Code Online (Sandbox Code Playgroud)