Haskell:显示IOArray的实例

时间:2017-08-06 21:10:58

标签: haskell

我正在学习Haskell并尝试使用可变数组(特别是IOArray)。我写了一个漂亮的打印机,它有以下类型:

disp :: Show a => IOArray Int a -> IO String

我没有设法摆脱IO部分,原因是

getBounds :: Ix i => a i e -> m (i, i) 

现在,我尝试使用disp为我的Show类型定义IOArray个实例,但IO会阻碍。

是否可以为Show创建IOArray个实例?

2 个答案:

答案 0 :(得分:3)

IOArray实际上并不是一个数组。它只是数组的引用。绝对地,您可以使用IOArray执行的所有操作都会在IO中生成一个操作。这是为什么?假设您可以使用纯代码索引IOArray

(!) :: IOArray Int a -> a

请考虑以下事项:

f :: IO (Char, Char)
f = do
  ar <- newArray (0 :: Int, 10 :: Int) 'a'
  let x = ar ! 3
  writeArray ar 3 'b'
  let y = ar ! 3
  return (x, y)

f应该产生什么?一个答案可能是它应该生成('a', 'b'),因为ar的第三个元素以'a'开头,然后更改为'b'。但那令人深感不安! ar ! 3如何同时拥有一个值而另一个值如何?这违反了纯函数式语言所依据的引用透明性的基本思想。所以你不能这样做。

答案 1 :(得分:-1)

Haskell中的AFAIK摆脱Monads既不可能也不正确。一些monad(比如Maybe和Either)有特殊的方法来解开它们的值,但不鼓励使用它们。如果你有任何包含在Monad上下文中的Haskell类型,你必须使用它并使用它而不需要解包和释放。对于您的情况,IO monad中的任何类型都不能转换(使用任何类型的函数,如Show)到没有IO M​​onad的任何类型。针对您的案例的一个解决方案是使用Haskell丰富的Monad函数和运算符来将内部类型(例如Int)转换为Char,之后您有一个IO String而不是IOArray,这反过来又可以打印出来。