Вызов монады IO внутри стрелы
Возможно, я поступаю неправильно, но я использую HXT для считывания некоторых данных вершин, которые я хотел бы использовать в массиве в HOpenGL. Массивы вершин должны быть Ptr, который создается путем вызова newArray. К сожалению, newArray возвращает IO Ptr, поэтому я не уверен, как его использовать внутри стрелки. Я думаю, что мне нужно что-то с объявлением типа, похожим на IO a -> Arrow a?
1 ответ
Тип IO a -> Arrow a
не имеет смысла; Arrow
это класс типа, а не определенный тип, очень похоже на Monad
или же Num
, В частности, экземпляр Arrow
это конструктор типов, принимающий два параметра, которые описывают вещи, которые могут быть составлены как функции, сопоставляя типы сквозными. Итак, преобразование IO a
Стрелка может быть названа концептуальной ошибкой типа.
Я не совсем уверен, что вы пытаетесь сделать, но если вы действительно хотите использовать IO
операции как часть Arrow
вам нужен ваш Arrow
экземпляр, чтобы включить это. Простейшей формой этого является наблюдение, что функции с такими типами, как a -> m b
для любого Monad
экземпляр может быть составлен очевидным образом. hxt
Пакет, кажется, предоставляет более сложный тип:
newtype IOSLA s a b = IOSLA { runIOSLA :: s -> a -> IO (s, [b]) }
Это какая-то смесь IO
, State
, а также []
монады, прикрепленные к функции, как указано выше, так что вы можете составить их, пройдя через все три Monad
на каждом шагу. Я действительно не использовал hxt
много, но если это Arrow
Если вы работаете, то довольно просто снять произвольную IO
функция, чтобы служить одним - просто передать значение состояния s
без изменений и превратить выходные данные функции в одноэлементный список. Возможно, уже есть функция, чтобы сделать это для вас, но я не видел ее вкратце.
По сути, вы хотели бы что-то вроде этого:
liftArrIO :: (a -> IO b) -> IOSLA s a b
liftArrIO f = IOSLA $ \s x -> fmap (\y -> (s, [y])) (f x)