Я понимаю, что остаточный тип является зависимым типом (в зависимости от модуля). Я читал о продлении DataKinds и был в состоянии определить его как следующее:Haskell - Как определить зависимый тип Remainder (т. Е. Rmndr modulo)?
{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators, GADTs #-}
data Nat = Zero | Succ Nat
data Rmndr modulo where
Nil :: Rmndr Zero
Rmndr :: Integer -> Rmndr modulo
Но тогда, когда я предваряюсь реализовать класс Eq, я застрял в состоянии
Rmndr x == Rmndr y = (x `mod` modulo) == (y `mod` modulo)
потому, что по модулю не значение, но тип. Даже если мы можем написать функцию следующим образом:
decat :: Nat -> Integer
decat Zero = 0
decat (Succ nat) = decat nat + 1
мы не можем использовать его следующим образом
instance Eq (Rmndr modulo) where
Nil == Nil = True
Rmndr x == Rmndr y =
x `mod` (decat modulo) == y `mod` (decat modulo)
потому, что «по модулю» в этом синтаксисе, не является переменной.
Может ли кто-нибудь помочь в этой головоломке? Большое спасибо!
Просто примечание: вы не можете делать индукции со встроенными типами naturals, потому что арифметика выполняется с типами семейств, которые не являются инъективными, и вы в конечном итоге не сможете убедить typechecker очень очевидных вещи.Это конкретное приложение хорошо подходит для типа nats, потому что индукции не требуется. – user2407038
@ user2407038: Ах, хорошая точка. Мое собственное использование также не требовало индукции, поэтому это не пришло в голову. Я столкнулся с другими случаями, когда я не мог убедить его в очень очевидных вещах, хотя :). –
Большое вам спасибо за подробный ответ! Я все еще перевариваю исходный код модульной арифметики и может появиться больше вопросов. Благодаря! – xiphoid