В Haskell это невозможно, так как типы стираются во время выполнения. То есть, когда программа запустится, в памяти нет информации о значении индекса let
в типе.
Чтобы преодолеть эту проблему, нам нужно заставить Haskell сохранять в памяти это значение во время выполнения. Обычно это делается с использованием вспомогательного типа singleton :
data Num = Zero | Succ Num
data SNum (n :: Num) where
SZero :: SNum 'Zero
SSucc :: SNum n -> SNum ('Succ n)
data Something (len :: Num) where
Some :: SNum len -> Something len
Используя это, вы можете легко написать
sToNum :: SNum n -> Num
sToNum SZero = Zero
sToNum (SSucc n) = Succ (sToNum n)
, а затем
toNum :: Something len -> Num
toNum (Some n) = sToNum n
Если вы ищите "haskell singletons", вы должны найти несколько примеров. Есть даже библиотека singletons
, чтобы частично автоматизировать это.
Если / когда будет выпущен «зависимый Haskell», у нас будут менее громоздкие инструменты. В настоящее время синглтоны работают, но иногда они доставляют хлопоты. Тем не менее, на данный момент мы должны использовать их.