如何用 prfun 替换静态断言?

How do you replace static assertions with prfuns?

考虑这个未精炼(但有效)程序:

#include "share/atspre_staload.hats"

datatype class =
        | mage   | fighter | thief | cleric
        | wizard | warrior | ninja | priest

fn promoteclass(job: class): class =
        case- job of
        | mage() => wizard()
        | fighter() => warrior()
        | thief() => ninja()
        | cleric() => priest()

fn getsomeclass(): class = mage()

val- wizard() = promoteclass(getsomeclass())

implement main0() = ()

wizard() 传递给 promoteclass() 是运行时错误,如果将 promoteclass(getsomeclass()) 更改为 return 而不是 wizard(),则会出现运行时错误].

哪个不行!我宁愿将这两个 - 符号翻转为 + 并在前两个错误情况下得到 编译时间 错误。如果意外转置提升案例可能是编译时错误,比如 priest() => cleric()

,那也很好

这种愿望导致了对上述内容的改进,这也很好用:

#include "share/atspre_staload.hats"

datatype class(int) =
        | mage(0)   | fighter(1) | thief(2) | cleric(3)
        | wizard(4) | warrior(5) | ninja(6) | priest(7)

fn promoteclass{n:int | n < 4}(job: class(n)): [m:int | m == n + 4] class(m) =
        case+ job of
        | mage() => wizard()
        | fighter() => warrior()
        | thief() => ninja()
        | cleric() => priest()

fn getsomeclass(): class(0) = mage()

val+ wizard() = promoteclass(getsomeclass())

implement main0() = ()

但我喜欢 做的是用数据道具和证明函数替换 n < 4 等。那可能吗?主要是我想这样做是为了更好地理解 ATS 中的定理证明,但它似乎也是获得与第二个示例相同的保证的途径,而没有它的所有冗长(特别是添加了额外的功能,对这些进行操作类).

这是我尝试做的:

#include "share/atspre_staload.hats"

datatype class(int) =
        | mage(0)   | fighter(1) | thief(2) | cleric(3)
        | wizard(4) | warrior(5) | ninja(6) | priest(7)

dataprop promotable(int) =
        | {n:int}promotable_yes(n)
        | {n:int}promotable_no(n)

prfun test_promotable.<>.{n:int}():<> promotable(n) =
        sif n < 4 then promotable_yes{n}() else promotable_no{n}()

fn promoteclass{n:int}(job: class(n)): [m:int] class(m) =
        let
                prval promotable_yes() = test_promotable{n}()
        in
                case+ job of
                | mage() => wizard()
                | fighter() => warrior()
                | thief() => ninja()
                | cleric() => priest()
        end

fn getsomeclass(): class(0) = mage()

val+ wizard() = promoteclass(getsomeclass())

implement main0() = ()

但我马上就被告知 prval 分配是非详尽的。

你得到的错误说 test_promotable 可能 return promotable_no,这是真的(因为测试可能会失败)。

不确定以下样式是否是您想要的:

dataprop
promotable(int) =
  | pf_mage(0)
  | pf_fighter(1)
  | pf_thief(2)
  | pf_cleric(3)

fn promoteclass{n:int}
  (pf: promotable(n) | job: class(n)): [m:int] class(m) =
  (
    case+ job of
    | mage() => wizard()
    | fighter() => warrior()
    | thief() => ninja()
    | cleric() => priest()
    | _ =/=>>
      (
        case+ pf of
        | pf_mage() => ()
        | pf_fighter() => ()
        | pf_thief() => ()
        | pf_cleric() => ()
      )
  )

以下代码应修复擦除错误:

fn promoteclass{n:int}
  (pf: promotable(n) | job: class(n)): [m:int] class(m) =
  (
    case+ job of
    | mage() => wizard()
    | fighter() => warrior()
    | thief() => ninja()
    | cleric() => priest()
    | _ =/=>> () where
      {
        prval () =
        (
        case+ pf of
        | pf_mage() => ()
        | pf_fighter() => ()
        | pf_thief() => ()
        | pf_cleric() => ()
        ) : [false] void
      }
  )

您可以将证明代码移动到证明函数中;证明函数的类型有点复杂。这是我拥有的:

prfn
not_promotable
  {n:int | n != 0&&n != 1&&n != 2&&n != 3 }
  (pf: promotable(n)):<> [false] void =
(
case+ pf of
| pf_mage() => ()
| pf_fighter() => ()
| pf_thief() => ()
| pf_cleric() => ()
)

fn promoteclass{n:int}
  (pf: promotable(n) | job: class(n)): [m:int] class(m) =
  (
    case+ job of
    | mage() => wizard()
    | fighter() => warrior()
    | thief() => ninja()
    | cleric() => priest()
    | _ =/=>> () where { prval () = not_promotable(pf) }
  )