Предположим, что список L с длиной n чередуется в списке J с длиной n + 1. Мы хотели бы знать, для каждого элемента J, который из его соседей из L больше. Следующая функция принимает L как свой вход и создает список K, также длины n + 1, так что i-й элемент из K является искомым соседом i-го элемента из J.
aux [] prev acc = prev:acc
aux (hd:tl) prev acc = aux tl hd ((max hd prev):acc)
expand row = reverse (aux row 0 [])
Я могу доказать себе, неформально, что длина результата этой функции (что я первоначально написано в Ocaml), является одним большим, чем длина ввода. Но я перескочил на Haskell (новый язык для меня), потому что меня заинтересовало способный доказать через систему типов, что этот инвариант имеет место. С помощью этот предыдущий ответ, я был чтобы получить следующее:
{-# LANGUAGE GADTs, TypeOperators, TypeFamilies #-}
data Z
data S n
type family (:+:) a b :: *
type instance (:+:) Z n = n
type instance (:+:) (S m) n = S (m :+: n)
-- A List of length 'n' holding values of type 'a'
data List a n where
Nil :: List a Z
Cons :: a -> List a m -> List a (S m)
aux :: List a n -> a -> List a m -> List a (n :+: (S m))
aux Nil prev acc = Cons prev acc
aux (Cons hd tl) prev acc = aux tl hd (Cons (max hd prev) acc)
Однако в последней строке появляется следующая ошибка:
* Could not deduce: (m1 :+: S (S m)) ~ S (m1 :+: S m)
from the context: n ~ S m1
bound by a pattern with constructor:
Cons :: forall a m. a -> List a m -> List a (S m),
in an equation for `aux'
at pyramid.hs:23:6-15
Expected type: List a (n :+: S m)
Actual type: List a (m1 :+: S (S m))
* In the expression: aux tl hd (Cons (max hd prev) acc)
In an equation for `aux':
aux (Cons hd tl) prev acc = aux tl hd (Cons (max hd prev) acc)
* Relevant bindings include
acc :: List a m (bound at pyramid.hs:23:23)
tl :: List a m1 (bound at pyramid.hs:23:14)
aux :: List a n -> a -> List a m -> List a (n :+: S m)
(bound at pyramid.hs:22:1)
Кажется, что мне нужно сделать, это научить компилятор, что (x :+: (S y)) ~ S (x :+: y)
. Возможно ли это?
В качестве альтернативы, есть ли лучшие инструменты для этой проблемы, чем система типов?