【问题标题】:Purpose of re-boxing pure value for GHCI为 GHCI 重新装箱纯值的目的
【发布时间】:2018-08-13 16:17:37
【问题描述】:

有人可以向我解释为什么在使用ghci 时我必须“重新装箱”单子返回的值吗?

 listAction=listDirectory "D:\\"
 lenAction=listAction>>=length 

错误:

Couldn't match type `Int' with `IO b0'
      Expected type: [FilePath] -> IO b0
        Actual type: [FilePath] -> Int

我不明白我的逻辑哪里有缺陷:

  1. 使用listAction 给我一个IO [FilePath]
  2. 我将listAction 的值拆箱为[FilePath],然后将其提供给length
  3. 现在length 不应该将结果作为纯函数打印到控制台吗?如果我说length [1,2,3] 不一样吗?

为什么我必须再次装箱?类型的单子的结果不是:[FilePath] 如果是这样,为什么它不能打印结果?

lenAction=list>>=return . length

【问题讨论】:

  • Re: (3): 不,length 不会隐式打印其结果。如果这就是你想要的,你必须要求它:例如listAction >>= print . length。可能会出现这种混淆,因为为了用户友好,ghci 通常会在您不注意的情况下为您隐式调用print 包装纯事物。它会在您输入的整个表达式周围包裹一个print(例如,如果该类型已检查,则可以插入print (listAction >>= length)),但不会深入到您的表达式内部以尝试猜测print 应该去哪里。

标签: haskell io-monad


【解决方案1】:

这只是一个类型错误。

>>= 的类型(与IO 一起使用时)是

(>>=) :: IO a -> (a -> IO b) -> IO b

也就是说,第二个参数必须是返回IO something 类型值的函数。 length 没有这样的类型,所以类型检查器会报错。

如您所见,return :: a -> IO a 可用于将值提升为 IO。这是解决问题的一种方法。

另一种方法是使用fmap:

fmap length listAction

这是因为fmap(与IO 一起使用时)是

fmap :: (a -> b) -> IO a -> IO b

(做同样事情的其他方式包括liftM length listActionlength <$> listAction。)

【讨论】:

  • liftM 通常仅用于定义fmap。其他用途有点过时了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 2011-02-28
  • 1970-01-01
相关资源
最近更新 更多