在 Arrow 中调用 IO Monad

6
也许我做错了,但我正在使用HXT读取一些顶点数据,并希望将其用于HOpenGL中的数组。 顶点数组需要是Ptr类型,可以通过调用newArray创建。不幸的是,newArray返回一个IO Ptr,因此我不确定如何在Arrow中使用它。我认为我需要一些类似于IO a -> Arrow a的类型声明?
1个回答

5
类型 IO a -> Arrow a 是没有意义的;Arrow 是一个类型类,而不是具体的类型,就像MonadNum一样。具体来说,Arrow的一个实例是一个类型构造器,它接受两个参数,描述可以像函数一样组合的东西,匹配类型端到端。因此,将IO a转换为箭头可能被称为概念上的类型错误。
我不确定你想做什么,但如果您真的想将IO操作作为Arrow的一部分使用,则需要您的Arrow实例包括这一点。 最简单的形式是观察到对于任何Monad实例的类型为a -> m b的函数可以以明显的方式组合。 hxt软件包似乎提供了更复杂的类型:
newtype IOSLA s a b = IOSLA { runIOSLA :: s -> a -> IO (s, [b]) }

这是一些 IOState[]monad的混合体,它们附加在一个函数上,使您可以组合它们通过每个步骤的三个Monad。我还没有真正使用过,但如果这些是你正在使用的Arrow,那么将任意的IO函数提升为其中之一就很简单——只需保持状态值不变,并将函数的输出转换成单例列表即可。可能已经有一个函数可以为您完成此操作,但我在简短的浏览中没有看到。

基本上,您需要像这样的东西:

liftArrIO :: (a -> IO b) -> IOSLA s a b
liftArrIO f = IOSLA $ \s x -> fmap (\y -> (s, [y])) (f x)

1
arrIO 似乎是他要找的函数。它的实现基本上与你的一样。 - hammar
@hammar: *啊哈!*感谢你,因为某种原因我以为它的名称中会有“提升”这个词。 - C. A. McCann
啊对,确切就是这样!每次我觉得箭头和单子概念已经理解了,结果我都得重新弄明白一遍... - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接