想象一下,我通过stdin读取了一个输入块,如下所示:
3
12
16
19
第一个数字是以下行数。我必须通过函数处理这些数字并报告由空格分隔的结果。
所以我写了这个主要功能:
main = do
num <- readLn
putStrLn $ intercalate " " [ show $ myFunc $ read getLine | c <- [1..num]]
当然,由于read getLine
,该函数无法编译。
但正确的(读取:Haskell方式)正确的方法是什么?是否可以将此功能写为单行?
答案 0 :(得分:2)
您可以使用<$>
(或fmap
)构建一系列monadic操作,并使用sequence
执行所有操作。
λ intercalate " " <$> sequence [show . (2*) . read <$> getLine | _ <- [1..4]]
1
2
3
4
"2 4 6 8"
答案 1 :(得分:2)
是否可以将此功能编写为单行?
当然,但main
功能的最后一行存在问题。因为您尝试将intercalate " "
应用于
[ show $ myFunc $ read getLine | c <- [1..num]]
我猜你希望后者有[String]
类型,但实际上它不是一个类型很好的表达式。怎么能修好?我们先来定义
getOneInt :: IO Int
getOneInt = read <$> getLine
为方便起见(我们将在代码中多次使用它)。现在,你的意思可能就像
[ show . myFunc <$> getOneInt | c <- [1..num]]
,如果myFunc
的类型与其他类型对齐,则类型为[IO String]
。然后,您可以将其传递给sequence
,以获得类型IO [String]
的值。最后,你可以通过&#34; (使用=<<
)
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方式)正确的方法是什么?
没有&#34;正确&#34;这样做的方式,但以下只是让我觉得更自然和可读:
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
答案 2 :(得分:2)
是否可以将此功能编写为单行?
嗯,它确实很简洁,但请亲自看看:
main = interact $ unwords . map (show . myFunc . read) . drop 1 . lines
那么,这是如何工作的?
interact :: (String -> String) -> IO ()
从STDIN获取所有内容,将其传递给给定函数,然后打印输出。unwords . map (show . myFunc . read) . drop 1 . lines :: String -> String
:
lines :: String -> [String]
在行尾打破字符串。drop 1
删除了第一行,因为我们实际上并不需要行数。map (show . myFunc . read)
将每个String
转换为正确的类型,使用myFunc
,然后将其转换回`String。unwords
与intercalate " "
基本相同。但是,请记住interact
对GHCi不是很友好。