伊德里斯:有界双

时间:2016-05-31 22:09:22

标签: dependent-type idris

我是伊德里斯的新手。我需要创建一个描述有界数字的数据。所以我用这样的构造函数制作了这样的数据:

data BoundedDouble : (a, b : Double) -> Type where
  MkBoundedDouble : (x : Double) -> 
                    {auto p : a <= x && x <= b = True} -> 
                    BoundedDouble a b

似乎在Doublea之间创建b。 这是一个简单的使用示例:

test : BoundedDouble 0.0 1.0
test = MkBoundedDouble 0.0 

有效。但现在我想为Num实现BoundedDouble接口。我试过这个:

Num (BoundedDouble a b) where
  (MkBoundedDouble x) + (MkBoundedDouble y) = 
    MkBoundedDouble (ifThenElse (x + y > b) 
                      (x + y - (b - a))
                      (ifThenElse (x + y < a)
                        (x + y + (b - a))
                        (x + y)))

但它不起作用,我想为什么,但我无法解释。 我该如何实施添加?

我不确切地知道应该做什么或阅读以理解它。

1 个答案:

答案 0 :(得分:3)

这里有两个问题。 Double arithmetic is defined with primitive functions.伊德里斯甚至无法证明a <= b = True -> b <= c = True -> a <= c = True(顺便说一下,它甚至都没有 - 所以这不是伊德里斯的错。)没有{{1}的证据。其他然后只是检查它,你尝试了a <= b = True

使用此类盲运行时证明(仅ifThenElse)时,Data.So非常有用。给定布尔检查… = True分支,但分支中的代码不知道检查结果。使用ifThenElse (a <= x) … …,您可以获得分支的结果,choose (a <= x)Left prfprf : So (a <= x)Right prf

我想如果添加两个有界双精度的结果会比上界更大,结果应该是这个上限。让我们先尝试一下:

prf : So (not (a <= x))

这已经有了类型,但它有漏洞。我们希望将import Data.So data BoundedDouble : (a, b : Double) -> Type where MkBoundedDouble : (x : Double) -> {auto high : So (a <= x)} -> {auto low : So (x <= b)} -> BoundedDouble a b Num (BoundedDouble a b) where (+) (MkBoundedDouble u) (MkBoundedDouble v) = let x = u + v in case (choose (a <= x), choose (x <= b)) of (Left _, Left _) => MkBoundedDouble x (Right _, _) => ?holeMin (_, Right _) => ?holeMax 设置为?holeMin,将MkBoundedDouble a设置为?holeMax。但是,MkBoundedDouble b现在需要两个证明:MkBoundedDoublehigh。对于low?holeMax x = bSo (a <= b)会有So (b <= b)。同样,Idris不知道每b <= b b : Double。所以我们需要再次选择获得这些证据:

             (_, Right _) => case (choose (a <= b), choose (b <= b)) of
                  (Left _, Left _) => MkBoundedDouble b
                  _ => ?what

因为Idris看不到b <= b,所以该功能将是部分的。我们可以在MkBoundedDouble u中欺骗和使用例如?what,因此该函数将进行类型检查并希望确实不会发生这种情况。

还有可能用力量说服类型检查器b <= b始终为真:

data BoundedDouble : (a, b : Double) -> Type where
    MkBoundedDouble : (x : Double) 
                      -> {auto rightSize : So (a <= b)}
                      -> {auto high : So (a <= x)}
                      -> {auto low : So (x <= b)}
                      -> BoundedDouble a b

DoubleEqIsSym : (x : Double) -> So (x <= x) 
DoubleEqIsSym x = believe_me (Oh)

Num (BoundedDouble a b) where
    (+) (MkBoundedDouble u) (MkBoundedDouble v) =
           let x = u + v
           in case (choose (a <= x), choose (x <= b)) of
             (Left _, Left _) => MkBoundedDouble x
             (Right _, _) => MkBoundedDouble a {high=DoubleEqIsSym a}
             (_, Right _) => MkBoundedDouble b {low=DoubleEqIsSym b}

或者我们可以更安全并在数据构造函数中放置上限和下限的证明,因此我们可以在?holeMin?holeMax中使用它们。这将是:

import Data.So

data BoundedDouble : (a, b : Double) -> Type where
    MkBoundedDouble : (x : Double) 
                      -> {auto rightSize : So (a <= b)}
                      -> {auto leftId : So (a <= a)}
                      -> {auto rightId : So (b <= b)}
                      -> {auto high : So (a <= x)}
                      -> {auto low : So (x <= b)}
                      -> BoundedDouble a b

Num (BoundedDouble a b) where
    (+) (MkBoundedDouble u) (MkBoundedDouble v) =
           let x = u + v
           in case (choose (a <= x), choose (x <= b)) of
             (Left _, Left _) => MkBoundedDouble x
             (Right _, _) => MkBoundedDouble a
             (_, Right _) => MkBoundedDouble b

你看,即使构造函数包含证明,它们也不会使实现复杂化。它们应该在实际的运行时代码中被删除。

但是,作为练习,您可以尝试为{/ p>实施Num

data BoundedDouble : (a, b : Double) -> Type where
    MkBoundedDouble : (x : Double)
                      -> {auto rightSize : So (a <= b)}
                      -> {auto high : So (a <= x)}
                      -> {auto low : So (x <= b)} 
                      -> BoundedDouble a b
    Min : {auto rightSize : So (a <= b)} -> BoundedDouble a b
    Max : {auto rightSize : So (a <= b)} -> BoundedDouble a b

可悲的是,伊德里斯的资源还不多。除了教程之外,还有a book正在开发中,我建议。它提供了比使用原始类型更平易近人的练习。 : - )