Ответ 1
Я не знаю, каково ваше определение retract
, но задано
retract :: Monad m => Free m a -> m a
retract (Pure a) = return a
retract (Impure fx) = fx >>= retract
и
liftF :: Functor f => f a -> Free f a
liftF fx = Impure (fmap Pure fx)
Обратите внимание, что (доказательства могут быть неправильными, делали это вручную и не проверяли их)
retract $ liftF x
= retract (Impure (fmap Pure x))
= (fmap Pure x) >>= retract
= (x >>= return . Pure) >>= retract
= x >>= \y -> (return $ Pure y) >>= retract
= x >>= \y -> (retract (Pure y))
= x >>= \y -> return y
= x >>= return
= x
поэтому у вас есть
retract (liftF x >>= liftF . f)
= retract ((Impure (fmap Pure x)) >>= liftF . f)
= retract $ Impure $ fmap (>>= liftF . f) $ fmap Pure x
= (fmap (>>= liftF . f) $ fmap Pure x) >>= retract
= (fmap (\y -> Pure y >>= liftF . f) x) >>= retract
= (fmap (liftF . f) x) >>= retract
= (liftM (liftF . f) x) >>= retract
= (x >>= return . liftF . f) >>= retract
= x >>= (\y -> (return $ liftF $ f y >>= retract)
= x >>= (\y -> retract $ liftF $ f y)
= x >>= (\y -> retract . liftF $ f y)
= x >>= (\y -> f y)
= x >>= f
это не означает, что Free m a
изоморфно m a
, просто retract
действительно свидетельствует о ретракции. Заметим, что liftF
не является монадным морфизмом (return
не переходит в return
). Free является функтором в категории функторов, но он не является монадой в категории монад (несмотря на то, что retract
очень похож на join
и liftF
, очень похож на return
).
EDIT: Обратите внимание, что ретракция подразумевает некоторую эквивалентность. Определить
~ : Free m a -> Free m a -> Prop
a ~ b = (retract a) ==_(m a) (retract b)
Затем рассмотрим фактор-тип Free m a/~
. Я утверждаю, что этот тип изоморфен m a
. Так как (liftF (retract x)) ~ x
, потому что (retract . liftF . retract $ x) ==_(m a) retract x
. Таким образом, свободная монада над монадой - это именно эта монада плюс некоторые дополнительные данные. Это точно так же, как утверждение, что [m]
является "по существу тем же", что и m
, когда m
является m
является моноидом.