如何在Haskell中从IO操作中获取正常值

Ben*_*ach 18 io monads haskell

我有以下功能:

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
Run Code Online (Sandbox Code Playgroud)

而且我想从中得到一个Chars价值,而不是 IO行动.我知道怎么做,或者甚至可能.

Chars基本上只是一个[Int]名为curData且Int名为curIndex的容器.细节并不重要,我只是想知道这个函数是否有办法返回一个Chars而不是一个IO Chars.

如果没有,我如何将此作为参数传递给一个带有Chars?的函数?我是Haskell IO的新手,但我不认为我希望所有Chars以参数为参数的函数都必须IO Chars作为参数,然后提取并重新打包它们.这似乎没必要.

谢谢!

Ric*_* T. 22

你不能,因为这会违反参考透明度.

Haskell中的IO就是这样精确地区分其结果和效果可能根据与环境/用户的交互而变化的动作以及当使用相同的输入参数调用它们时结果不会改变的纯函数.

为了将结果传递给Chars输入输入的纯函数,必须将IO操作调用到另一个IO操作中,将结果与<-操作符绑定到变量并将其传递给纯函数.伪代码示例:

myPureFunction :: Chars -> ...

otherAction :: Chars -> IO ()
otherAction cs = do
  myChars <- get cs
  let pureResult = myPureFunction myChars
  ...
Run Code Online (Sandbox Code Playgroud)

如果您是haskell中IO的新手,您可能希望查看" 了解大家好的Haskell"中的输入和输出章节!真实世界Haskell.

实际上有一种方法可以简单地从IO操作中获得纯粹的价值,但在你的情况下你不应该这样做,因为你正在与环境进行交互:只有在你可以保证你的时候,不安全的方式才行不违反参考透明度.

  • 不,您不应该尽可能放弃类型保证的引用透明度。因此,就让这些函数顺其自然吧,不要让它们返回类似“IO a”的东西。 (2认同)

Dan*_*her 9

这是不可能的(我撒谎,有一种非常不安全的方式来欺骗你的方式).

关键是如果执行任何I/O,程序的行为和结果可能不仅仅依赖于使用函数的显式参数,因此必须通过使用它来声明类型IO something.

你可以IO a通过绑定结果main(或者调用from main)来使用纯函数中的动作结果,然后应用纯函数,将结果绑定在a中let,

cs ::Chars
cs = undefined

main = do
  chars <- get cs
  let result = pureFunction chars
  print result
Run Code Online (Sandbox Code Playgroud)

或者,如果您要应用的功能chars具有类型Chars -> IO b

main = do
    chars <- get cs
    doSomething chars
Run Code Online (Sandbox Code Playgroud)