【问题标题】:Haskell: use list generated in IO function in another, non-IO functionHaskell:在另一个非 IO 函数中使用 IO 函数中生成的列表
【发布时间】:2020-03-17 22:06:25
【问题描述】:

我正在使用String -> IO [x] 函数将文件的内容读入列表中,其中列表中的每个元素都是文件中的一个单词。

但是,我想使用[x] 列表作为另一个函数的输入。我的问题是我不明白如何访问基本的[x] 列表,而不是在我的初始函数中生成的IO [x] 列表。我一直在通过使用 GHCI 和使用

来解决这个问题
k <- listRead "file.txt"

然后在我的下一个函数中使用 k 作为输入,该函数仅将列表 [x] 作为输入。

如何使用“内部”列表[x] 而不是我的初始函数返回的IO [x]

【问题讨论】:

  • 你不能因为IO a不是IO操作的结果,它是IO操作的“配方”。但是,您可以使用 k 变量,从而进行函数调用。

标签: haskell io monads function-call purely-functional


【解决方案1】:

这就是 Monad 类型类的用途。

foo :: String -> IO [SomeType]
bar :: [SomeType] -> IO SomeOtherType

然后

baz :: String -> IO SomeOtherType
baz name = foo name >>= bar

(或在导入Control.Monadbaz = foo &gt;=&gt; bar 之后)。

如果你只有一些函数bar' :: [SomeType] -&gt; SomeOtherType,那么你可以定义

bar :: [SomeType] -> IO SomeOtherType
bar = return . bar'

请注意,您永远无法真正“获取”[SomeType] 类型的值;您只能在执行 IO 操作后创建使用该值的新 IO 操作。

【讨论】:

  • bar = return . bar' 的替代方法是将Functor 实例用于IO,即baz = fmap bar' . foo
【解决方案2】:

简单地说,将您在 GHCi 中使用的那一行放入 do 块中:

do
    k <- listRead "file.txt"    
    let r = yourPureFunction k
    return r

do notation 中,对于x &lt;- mx 行,每当mx :: M <b>a</b> 对于某些Monad M,我们就有x :: <b>a</b>

因此yourPureFunction :: <b>a</b> -&gt; <b>b</b> 应用于M内部a 参数,并表示组合的一元值do 块的类型为M <b>b</b>,因为return 的类型为return :: <b>b</b> -&gt; M <b>b</b>,而do 块的整体类型是其最后一个表达式的类型。

上面的代码恰好是 / 可编码为 / (return . yourPureFunction) =&lt;&lt; listRead "file.txt" 的更高级别的语法表示,这也是 the same as yourPureFunction &lt;$&gt; listRead "file.txt"(带有 (&lt;$&gt;) = fmap),但这不是重点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 2014-07-31
    • 2016-03-20
    • 1970-01-01
    相关资源
    最近更新 更多