Я пытаюсь понять, как это очень абстрактно-рекурсивная функция из пакета Haskell recursion-schemes
работает (или, на самом деле, что он делает!) - от this file:Как gpostpro «убегает от монады»?
class Functor (Base t) => Corecursive t where
[...]
-- | A generalized postpromorphism
gpostpro
:: (Recursive t, Monad m)
=> (forall b. m (Base t b) -> Base t (m b)) -- distributive law
-> (forall c. Base t c -> Base t c) -- natural transformation
-> (a -> Base t (m a)) -- a (Base t)-m-coalgebra
-> a -- seed
-> t
gpostpro k e g = a . return where a = embed . fmap (ana (e . project) . a . join) . k . liftM g
В частности, то, что я хочу, чтобы понять: как он применяет функцию g
, которая упоминает конструктор типа монады m
, но затем возвращает значение типа t
, которое не упоминает или не зависит от m
? Я думал, что победить из произвольных монадов невозможно в Хаскелле!
Сначала я загрузил исходный файл в Intero, чтобы попытаться использовать его функцию типа в точке, но эта попытка failed.
Затем я загрузил его в GHCi, используя cabal repl
, и попытался следовать за типами через скомпонованные функции по одному, используя GHCi, чтобы помочь с типом вывода, комментируя различные биты определения. Однако, когда я добрался до fmap
, я не смог понять, что закомментировать, потому что, если я раскомментировал рекурсивный вызов a
, но прокомментировал другие вещи, я подумал, что он, вероятно, даже не будет компилироваться, потому что частично закомментированный определениеa
не будет иметь подходящий тип.
Вы можете поместить '_' вместо любого выражения, чтобы спросить GHC о его типе. – arrowd
И по. escaping: 't' имеет класс« Рекурсивный », что означает, что он имеет тип' * -> * '. Это указывает на то, что тип возврата gpospro не ускользает и что-то завершается. Скорее всего, это монада. – arrowd
@arrowd Вышеуказанная подпись типа была бы невозможна, если бы это было так, потому что у вас не может быть типа возврата, который имеет вид '* -> *'. –