我有以下功能:
get :: Chars -> IO Chars
get cs = do
char <- getChar
let (dats, idx) = (curData cs, curIndex cs)
let (x,y:xs) = splitAt idx dats
let replacement = x ++ (ord char) : xs
return $ Chars replacement idx
我希望从中获取Chars
值,不 IO操作。我没有想法如何做到这一点,或者甚至可能。
Chars基本上只是一个名为curData的[Int]
和名为curIndex的Int
的容器。具体细节并不重要,我只是想知道这个函数是否有办法返回Chars
而不是IO Chars
。
如果没有,我如何将其作为参数传递给采用Chars
的函数?我是Haskell IO的新手,但我认为我不希望所有以Chars
为参数的函数都必须将IO Chars
作为参数,然后提取并重新打包它们。这似乎没必要。
谢谢!
答案 0 :(得分:21)
你不能,因为这会违反referential transparency。
Haskell中的IO就是这样做的,以区分根据与环境/用户的交互而结果和效果可能不同的动作以及当使用相同的输入参数调用结果时结果不会改变的纯函数。
为了将结果传递给输入Chars
的纯函数,必须将IO操作调用到另一个IO操作中,将结果与<-
运算符绑定到变量并传递这是你的纯粹功能。伪代码示例:
myPureFunction :: Chars -> ...
otherAction :: Chars -> IO ()
otherAction cs = do
myChars <- get cs
let pureResult = myPureFunction myChars
...
如果您是haskell中IO的新手,您可能希望查看Learn You a Haskell for a Great Good!和Real World Haskell中的输入和输出章节。
实际上有一种方法可以简单地从IO操作中获取纯值,但在您的情况下,您不应该这样做,因为您正在与环境交互:只有当您能保证时,不安全的方式才可以你没有违反参考透明度。
答案 1 :(得分:9)
这是不可能的(我撒谎,有一种非常不安全的方法可以欺骗你。)
关键是如果执行了任何I / O,程序的行为和结果可能不仅仅依赖于使用函数的显式参数,因此必须通过使用IO something
来声明类型
通过将结果绑定在IO a
(或从main
调用的内容)然后应用纯函数,绑定结果,在纯函数中使用main
操作的结果在let
,
cs ::Chars
cs = undefined
main = do
chars <- get cs
let result = pureFunction chars
print result
或者,如果您要应用于chars
的功能类型为Chars -> IO b
main = do
chars <- get cs
doSomething chars