Мне хочется понять абстрактную концепцию неподвижной точки функтора, однако я все еще пытаюсь выяснить точную реализацию ее и ее катаморфизма в Хаскеле.
Например, если я определю,согласно книге «Теория категорий для программистов» - стр. 359, следующая алгебра
-- (Int, LiftF e Int -> Int)
data ListF e a = NilF | ConsF e a
lenAlg :: ListF e Int -> Int
lenAlg (ConsF e n) -> n + 1
lenAlg NilF = 0
по определению катаморфизма, следующую функцию можно применить к фиксированной точке ListF, которая представляет собой список,чтобы вычислить его длину.
cata lenAlg :: [e] -> Int
cata lenAlg = lenAlg . fmap (cata lenAlg) . unFix
У меня есть две путаницы.Во-первых, как компилятор Haskell узнает, что List является THE фиксированной точкой ListF?Концептуально я знаю, что это так, но как узнает компилятор, то есть что, если мы определим другой List, который будет таким же, как List, могу поспорить, что компилятор автоматически не делает вывод, что List 'тоже является фиксированной точкой ListF, или делаетЭто?(Я был бы удивлен).
Во-вторых, из-за рекурсивной природы cata lenAlg, он всегда пытается разблокировать внешний слой конструктора данных, чтобы показать внутренний слой функтора (это моя интерпретация дажеправильно кстати?).Но что, если мы уже находимся на листе, как мы можем вызвать этот вызов функции?
fmap (cata lenAlg) Nil
В качестве примера, может ли кто-нибудь помочь написать трассировку выполнения для пояснения вызова ниже функции?
cata lenAlg Cons 1 (Cons 2 Nil)
Я, вероятно, упускаю что-то очевидное, однако я надеюсь, что этот вопрос все еще имеет смысл для других людей, которые разделяют подобные заблуждения.
Краткое содержание ответа
@ nm ответил на мой первый вопрос, указав, что для того, чтобы компилятор Haskell выяснил, что Functor A является фиксированной точкой Functor B, нам нужно быть явными.В этом случае это
type List e = Fix (ListF e)
@ luqui и @Will Ness указали, что вызов fmap (cata lenAlg) на листе, который в данном случае является NilF, вернет NilF назад, из-за определенияof fmap.
-- f :: a -> b
fmap f (ConsF e a) = ConsF e (f b)
fmap f NilF = NilF
Я бы принял ответ @ nm, так как он непосредственно касался моего первого (большего) вопроса, но мне нравятся все три ответа.Большое спасибо за вашу помощь!