Скажем у меня есть некоторые Монадические ТипуКак применять пользовательские Монада Transformer
data Example a = CheckIt {unwrap :: a}
instance Functor Example where
fmap f (CheckIt x) = CheckIt (f x)
instance Applicative Example where
pure = CheckIt
CheckIt f <*> CheckIt x = CheckIt (f x)
instance Monad (Example) where
return = CheckIt
[email protected](CheckIt a) >>= f = f a
и у меня есть функция, которая возвращает [a]
на основе некоторых входных сигналов:
fetchList :: b -> [Int]
fetchList _ = [1,2,3,4]
и функцию, которая возвращает IO [a] (упрощенное из реальной реализации):
basicIoWrap :: [a] -> IO [a]
basicIoWrap x = return x
и я хочу запустить этот IO, а затем извлечь Пример [а] от него:
Следующая не работает:
foo :: b -> Example [a]
foo val = (basicIoWrap (fetchList val)) >>= \list -> return list
жалуется на различные типы монадных
Couldn't match type ‘IO’ with ‘Example’
Expected type: Example [a]
Actual type: IO [Int]
Так что я понимаю, что это именно UseCase для Monad трансформаторов, но Я действительно изо всех сил пытаюсь понять, как применять их в контексте. Скажем, у меня был трансформатор:
newtype ExampleT m a = ExampleT {runExampleT :: m (Example a)}
и я перефразировал свою подпись Foo :: б -> ExampleT (IO [а])
Я неясно, что тело функции будет выглядеть, и также, как я в конечном итоге извлечу из него пример [a]? Не будет runExampleT ExampleT (IO [a])
дать IO [Example a]
, таким образом, просто пробивая проблему с несколькими Монадами дальше по дороге?
В дополнение к различным небезопасным функциям «выключения» вы не можете удалить список из монады ввода-вывода, чтобы вернуть «Пример [a]». Причина, по которой трансформатор IoT не существует, заключается в том, что монада IO, если она используется, должна находиться в основе стека, то есть внешняя самая монада любого стека - 'IO'. – chepner
Итак, как это вообще происходит в этой ситуации? –
Монадный трансформатор - это прежде всего добавление поведения к существующей монаде, а не извлечение из нее значений. Если 'foo' возвращает' IO (Пример [a]) '(поскольку @ user2297560 избил меня, чтобы предложить), то относительно легко написать функцию с типом' bar :: Example [a] -> IO [a] 'для извлечения внутреннего списка (сохраняя его в контексте IO). С такой функцией вы можете написать 'foo >> = bar'. – chepner