Haskell 从IO(a)中展开a
过去两周我一直在学习Haksell,并决定在Hackerrank等地尝试挑战。这需要学习IO。我已经阅读了许多关于stackExchange的答案,其大意是您不需要打开IO a。。您只需在IO函数中操作该数据。在这种情况下,如果不允许我将数据从main发送到纯函数,那么所有纯函数的意义何在?下面是一些代码,它读取多少个测试用例,然后为每个测试用例读取N个有序对Haskell 从IO(a)中展开a,haskell,Haskell,过去两周我一直在学习Haksell,并决定在Hackerrank等地尝试挑战。这需要学习IO。我已经阅读了许多关于stackExchange的答案,其大意是您不需要打开IO a。。您只需在IO函数中操作该数据。在这种情况下,如果不允许我将数据从main发送到纯函数,那么所有纯函数的意义何在?下面是一些代码,它读取多少个测试用例,然后为每个测试用例读取N个有序对 main = do test <- getLine replicateM (read test) doTest
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)
但我似乎不知道该怎么做。任何关于如何使用我从用户那里读到的数据调用此函数的帮助或建议都将不胜感激。或者,如果我从错误的角度出发,我应该做什么的指针也会起作用
编辑:通过阅读这里的许多其他问题,我得到了一个普遍的想法,一旦你的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。首先,如果使用
x首先,如果使用x,则无法将IO a
转换为a
。您需要使用类似于fmap validFunction
的方法来获取IO[(Int,Int)]->IO Bool
,并使用它。一旦你执行了IO,你就永远不会有一个类型不显示IO正在被执行——是的,从我读到的所有答案中我都能理解。我似乎找不到任何清晰的例子来展示我所需要的语法。这一切似乎都涉及到留在主程序中的代码。我找不到任何使用您建议的语法从do块调用“纯函数”的代码。您试图在哪里调用validFunction
rs
仅绑定在doTest
的定义中,因此您可能需要类似fmap validFunction doTest
的内容。如果在doTest
内部调用它,则将返回rs
替换为fmap validFunction rs
@chepner:rs
已经是[(Int,Int)]
。你的意思是return(validFunction rs)
。当人们谈论“在IO monad中处理值”时,他们并不意味着所有函数都必须使用IO monad。它们意味着你把一组函数放在一起,最终结果(通常称为main
)在IO单子中。你不能将IO a
转换为a
。您需要使用类似于fmap validFunction
的方法来获取IO[(Int,Int)]->IO Bool
,并使用它。一旦你执行了IO,你就永远不会有一个类型不显示IO正在被执行——是的,从我读到的所有答案中我都能理解。我似乎找不到任何清晰的例子来展示我所需要的语法。这一切似乎都涉及到留在主程序中的代码。我找不到任何使用您建议的语法从do块调用“纯函数”的代码。您试图在哪里调用validFunction
rs
仅绑定在doTest
的定义中,因此您可能需要类似fmap validFunction doTest
的内容。如果在doTest
内部调用它,则将返回rs
替换为fmap validFunction rs
@chepner:rs
已经是[(Int,Int)]
。你的意思是return(validFunction rs)
。当人们谈论“在IO monad中处理值”时,他们并不意味着所有函数都必须使用IO monad。他们的意思是你把一组函数放在一起,最终结果(通常称为main
)在IO单子中。很好的解释。不幸的是,在我所做的一切中,我确实返回了有效的函数rs,但是缺少()或$。我总是忘记它的右关联。@TonyChamberlainreturn
是一个函数,而不是一个关键字。这是一个人必须记住的关键。很好的解释。不幸的是,在我所做的一切中,我确实返回了有效的函数rs,但是缺少()或$。我总是忘记它的右关联。@TonyChamberlainreturn
是一个函数,而不是一个关键字。这是一个人必须记住的关键。
putStrLn . f . validFunction $ rs
foo :: Int -> Char
foo = …
bar :: IO Int
bar = …
fooDo :: IO Char
fooDo = do
number <- bar
return (foo number) -- apply foo directly on number
liftedFoo :: IO Int -> IO Char
liftedFoo = fmap foo
fooDo = fmap foo readLn
doTest :: IO [(Int, Int)]
doTest = do
query <- getLine
rs <- replicateM (read query) readPair
return rs
doTest :: IO Bool
doTest = do
query <- getLine
rs <- replicateM (read query) readPair
return (validFunction rs)
-- ^^^^^^^^^^^^^^^^^^
-- no IO inside here
-- ^^^^^^
-- back
-- to IO
doTest :: IO Bool
doTest = do
query <- getLine
fmap validFunction (replicateM (read query) readPair)