Предположим, что я определяю свой собственный тип списка.В зависимости от типизированной карты - не может быть ошибкой?
data MyVec : Nat -> Type -> Type where
MyNil : MyVec Z a
(::) : a -> MyVec k a -> MyVec (S k) a
И myMap
функция служит fmap
для MyVec
:
myMap : (a -> b) -> MyVec k a -> MyVec k b
myMap f MyNil = ?rhs_nil
myMap f (x :: xs) = ?rhs_cons
Попытка решить ?rhs_nil
дыру в моей голове:
:t ?rhs_nil
являетсяMyVec 0 b
- достаточно справедливо - я нужен конструктор t шляпа возвращается
MyVec
параметризованоb
и мне нужноk
быть0
(илиZ
), и я могу видеть, чтоMyNil
индексируетсяZ
и параметризовано угодно, так что я могу использоватьb
легко, поэтому?rhs_nil
=MyNil
и typechecks, денди :t ?rhs_cons
являетсяMyVec (S k)
- мне нужен конструктор, который возвращает
MyVec
параметризованоb
и мне нужноk
быть(S k)
Я вижу, что конструктор (::)
строит список, проиндексированный (S k)
, и я пытаюсь его использовать. Первый аргумент должен быть типа b
, учитывая, что я строю MyVec <> b
и единственный способ получить его - применить x
до f
.
myMap f (x :: xs) = f x :: <>
Теперь я запутаться. RHS из (::)
должна быть MyVec k b
, почему я не могу просто использовать MyNil
конструктор, с объединительным/замещением k == Z
(тот MyNil
) дает мне получать:
myMap f (x :: xs) = f x :: MyNil
Я понимаю, что мне нужно recurse и имеют = f x :: myMap f xs
, но как компилятор знает, сколько раз должен использоваться конструктор (::)
? Как он выводит правильный k
для этого случая, не позволяя мне использовать Z
.
Вы можете расширить это. Я думаю, что многие люди не понимают, что '(x :: xs): Vec ka' уже был создан с помощью' (: :) ', поэтому' xs' распаковывается из преемника, что дает список 1 элемент короче. – ScarletAmaranth