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