2015-02-18 7 views
3

Я работаю немного с Идрисом и я написал тип вероятностей - Float сек между 0.0 и 1.0:Как вы доказываете, что вероятности замыкаются при умножении на зависимые типы?

data Probability : Type where 
    MkProbability : (x : Float) -> ((x >= 0.0) && (x <= 1.0) = True) -> Probability 

Я хочу, чтобы иметь возможность умножать:

multProbability : Probability -> Probability -> Probability 
multProbability (MkProbability p1 proof1) (MkProbability p2 proof2) = 
    MkProbability (p1 * p2) ??? 

Как я могу доказать, что p1 * p2 всегда будет вероятностью?

+0

Какова теория «Float's in Idris»? Напр. рациональные представления, представленные как «Int:/Nat» (так, например, 0,5 будет отображаться как «1:/1», так как мы предполагаем неявный «Suc' в знаменателе, чтобы избежать нулей), вы определяете порядок так, что' 0 <= p :/q <= 1' эквивалентно '0 <= p <= Suc q', то все, что вам нужно доказать, это' 0 <= p1 <= Suc q1 -> 0 <= p2 <= Suc q2 -> 0 <= (p1 * p2) <= (Suc q1 * Suc q2) ', что достаточно легко сделать через монотонность умножения. – Cactus

ответ

3

Я бы удалил числа с плавающей запятой из картинки. У вас почти всегда будут проблемы с примитивами, но особенно при работе со странными деталями типа IEEE 754.

Вместо этого, я бы представляют вероятности, используя тип отношения:

record Probability : Type where 
    MkProbability : (numerator : Nat) -> 
        (denominator : Nat) -> 
        LTE numerator (S denominator) -> 
        Probability 

LTE представляет собой тип, где значения существуют только тогда, когда первый Nat меньше или равен второму Nat. (S denominator) должен гарантировать, что у нас нет знаменателя нуля. Это означает, что MkProbability 2 1 (LTESucc LTEZero) действителен и представляет вероятность 1.0, выглядит странно, но обеспечивает достоверность.

Мы можем затем получить Float из типа:

toFloat : Probability -> Float 
toFloat (MkProbability n d _) = 
    fromInteger (toIntegerNat n)/fromInteger (toIntegerNat (S d)) 

Другим преимуществом является то, что это с произвольной точностью, пока мы не преобразовать в Float.

Проблема в том, что вам, вероятно, придется строить большие значения LTE. Использование isLTE для значений времени выполнения, вероятно, поможет здесь!