【发布时间】:2017-08-31 00:14:39
【问题描述】:
过去两周我一直在学习 Haskell,并决定在 HackerRank 等地方尝试挑战。这需要学习IO。我在 StackExchange 上阅读了很多答案,一般要点是您不要打开 IO a,您只需在 IO 函数中操作该数据。在这种情况下,如果我不允许将数据从 main 发送给它们,那么所有纯函数的意义何在?这是一些读取多少个测试用例的代码,然后为每个测试用例读取 N 个有序对。
main = do
test <- getLine
replicateM (read test) doTest
doTest = do
query<-getLine
rs<-replicateM (read query) readPair
return rs -- just here to make the file compile
readPair :: IO (Int, Int)
readPair = do
input <- getLine
let a = words input in return (read (a!!0) :: Int, read (a!!1) ::Int)
此时我在rs 中有一个IO [(Int, Int)]。我想将该数据发送到此函数:
validFunction :: [(Int,Int)]->Bool
validFuntion [] = True
validFunction (x:[]) = True
validFunction (x:xs) = (not $ elem (snd x) (fmap snd xs)) && validFunction xs
但我似乎无法弄清楚如何做到这一点。任何有关如何使用我从用户那里读取的数据调用此函数的帮助或建议将不胜感激。或者,如果我从错误的角度出发,那么我应该做什么的指针也会起作用。
编辑:通过阅读这里的许多其他问题,我现在有了一个大致的想法,即一旦你进入IO,你就会被困在那里。但我似乎找不到使用IO 数据调用纯函数并取回IO 数据的语法。我尝试了以下一些方法:
fmap validFunction [rs] :: IO Bool -- tried it with just rs without [] as well
mapM validFunction [rs] :: IO Bool
validFunction rs :: IO Bool
我能够让它工作:
putStrLn . f . validFunction $ rs
虽然我仍然不清楚为什么这会让您将IO [(Int, Int)] 传递给validFunction。
【问题讨论】:
-
你不能把
IO a变成a。您需要使用fmap validFunction之类的东西来获取IO [(Int,Int)] -> IO Bool并改用它。一旦你执行了 IO,你永远不会有一个不显示 IO 正在执行的类型——按照设计。 -
是的,我从我读过的所有答案中了解到这一点。我似乎找不到任何明确的例子来显示我需要的语法。这一切似乎都涉及留在主目录中的代码。我找不到使用您建议的语法从 do 块调用“纯函数”的任何代码。
-
你想在哪里打电话给
validFunction?rs只绑定在doTest的定义内,所以你可能想要像fmap validFunction doTest这样的东西。如果将其称为 insidedoTest,则将return rs替换为fmap validFunction rs。 -
@chepner:
rs已经是[(Int, Int)]。你的意思是return (validFunction rs)。 -
当人们谈论“在 IO monad 中处理值”时,他们并不意味着您的所有函数都必须使用 IO monad。他们的意思是你把一堆函数放在一起,最终结果(通常称为
main)在 IO monad 中。