甚至可以将此函数编写为单行吗?
当然可以,但是函数的最后一行有问题main
。因为你想intercalate " "
申请
[ show $ myFunc $ read getLine | c <- [1..num]]
我猜你希望后者有 type [String]
,但它实际上不是一个类型良好的表达式。这怎么能解决?我们先定义
getOneInt :: IO Int
getOneInt = read <$> getLine
为方便起见(我们将在代码中多次使用它)。现在,你的意思可能是这样的
[ show . myFunc <$> getOneInt | c <- [1..num]]
其中,如果 的 类型myFunc
与其余的一致,则具有 type [IO String]
。然后,您可以将其传递给以sequence
获取类型的值IO [String]
。最后,您可以“传递”(使用=<<
)到
putStrLn . intercalate " "
为了获得所需的单线:
import Control.Monad ( replicateM )
import Data.List ( intercalate )
main :: IO ()
main = do
num <- getOneInt
putStrLn . intercalate " " =<< sequence [ show . myFunc <$> getOneInt | c <- [1..num]]
where
myFunc = (* 3) -- for example
getOneInt :: IO Int
getOneInt = read <$> getLine
在 GHCi 中:
λ> main
3
45
23
1
135 69 3
但是,代码是否惯用且可读?没那么多,在我看来...
[...]正确(阅读:Haskell方式)正确执行此操作的方法是什么?
没有“正确”的做法,但以下内容对我来说更自然和可读:
import Control.Monad ( replicateM )
import Data.List ( intercalate )
main :: IO ()
main = do
n <- getOneInt
ns <- replicateM n getOneInt
putStrLn $ intercalate " " $ map (show . myFunc) ns
where
myFunc = (* 3) -- replace by your own function
getOneInt :: IO Int
getOneInt = read <$> getLine
或者,如果您想避开do
符号:
main =
getOneInt >>=
flip replicateM getOneInt >>=
putStrLn . intercalate " " . map (show . myFunc)
where
myFunc = (* 3) -- replace by your own function