我正在与Idris合作,我已经写了一个概率类型 - 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 :(得分: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
作为运行时值可能会有所帮助!