我正在学习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
个实例?
答案 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 Monad的任何类型。针对您的案例的一个解决方案是使用Haskell丰富的Monad函数和运算符来将内部类型(例如Int)转换为Char,之后您有一个IO String而不是IOArray,这反过来又可以打印出来。