Вызов монады IO внутри стрелы - PullRequest
6 голосов
/ 31 августа 2011

Возможно, я поступаю неправильно, но я использую HXT для считывания некоторых данных вершин, которые я хотел бы использовать в массиве в HOpenGL.Вершинные массивы должны быть Ptr, который создается путем вызова newArray.К сожалению, newArray возвращает IO Ptr, поэтому я не уверен, как его использовать внутри стрелки.Я думаю, что мне нужно что-то с объявлением типа, похожим на IO a -> Arrow a?

1 Ответ

5 голосов
/ 31 августа 2011

Тип 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)
...