Я пытаюсь определить функцию (congruentialMethod
) в Идрисе, которая среди прочего применяет арифметику модуля к некоторым аргументам, предоставленным моей функции.Арифметика модуля требует, чтобы второй аргумент был ненулевым, поэтому я попытался использовать modNatNZ
и добавить доказательство к моей сигнатуре типа функции.Тем не менее, я чувствую, что моя попытка оказывается очень неуклюжей.
Прежде всего, когда я определяю значение, которое в итоге становится вторым аргументом функции модуля (let m : Nat = 2147483647
), -Я должен выполнить несколько неуклюжихсопоставление регистра, чтобы убедить Идриса, что значение больше нуля.Если я этого не сделаю, тогда проверка типов будет длиться вечно.
Во-вторых, я не совсем понимаю, почему я должен предоставить доказательство при вызове моей функции (congruentialMethod
).Я указал доказательство как auto
в сигнатуре функции, полагая, что Идрис сможет вывести его.
module Random
%default total
getUnixEpoch : IO Nat
getUnixEpoch = do time <- foreign FFI_C "#(unsigned long)time(NULL)" (IO Int)
pure $ fromInteger $ cast time
congruentialMethod : (seed : Nat) -> (a : Nat) -> (b : Nat) -> (m : Nat) -> {auto prf : (m = Z) -> Void} -> Stream Double
congruentialMethod seed a b m {prf} =
(cast seed) / (cast m) :: loop seed
where
loop : (prev : Nat) -> Stream Double
loop prev = let n = modNatNZ (a * prev + b) m prf
in (cast n) / (cast m) :: loop n
main : IO ()
main = do time <- getUnixEpoch
putStrLn $ "seed: " ++ (cast time)
let a : Nat = 16807
let b : Nat = 0
let m : Nat = 2147483647
case m of
Z => ?shouldnt_happen
S m' => do let random_number_stream = congruentialMethod time a b (S m') {prf = SIsNotZ}
?continue
Можно ли как-то избежать передачи доказательства моей функции congruentialMethod
?и есть ли менее неуклюжий способ убедить Идриса, что let m : Nat = 2147483647
больше нуля (вместо использования сопоставления регистра) ?
РЕДАКТИРОВАТЬ: еще одна проблема сэтот код выглядит так, что выполнение вычислений с Nat
выполняется крайне медленно.Использование Int
, mod
и изменение функций на partial
позволяет быстро генерировать числа.Очевидно, что нас заставляют определять функции как partial
отстой .. Но, возможно, это материал для другого вопроса ...