如何将类型映射到 Idris/Agda/Coq 中的值?

How to map Type to Value in Idris/Agda/Coq?

我正在尝试定义一个名为 byteWidth 的函数,它捕获关于 "get byte width of specific atomic type".

的用法

我的第一次试用:

byteWidth : Type -> Int
byteWidth Int = 8
byteWidth Char = 1

Idris 编译器抱怨:"When checking left hand side of byteWidth: No explicit types on left hand side: Int"


我的第二次试用:

interface BW a where
  byteWidth : a -> Int

implementation BW Int where
  byteWidth _ = 8

implementation BW Char where
  byteWidth _ = 1

在这种情况下,我只能像 byteWidth 'a' 那样使用 byteWidth 而不能使用 byteWidth Char

在 Idris 中,你不能模式匹配一​​个类型,假设你可以,任何人都不可能枚举所有可能的类型,所以它不可能是全部的。

你唯一需要的额外事情是关于类型 a 在某个特定集合中的证明,我们将此命题命名为 ByteWidthAvailable.

data ByteWidthAvailable : Type -> Type where
  IntBWA : ByteWidthAvailable Int
  ChaBWA : ByteWidthAvailable Char

total
byteWidth : (a : Type) -> {auto prf: ByteWidthAvailable a} -> Int
byteWidth _ {prf = IntBWA} = 8
byteWidth _ {prf = ChaBWA} = 1

这里唯一的技巧是 Idris 提供的 auto 命令,它有助于在调用站点自动生成证明,这样您就可以像 byteWidth Char 一样调用 byteWidthbyteWidth Char {prf = ChaBWA}.

您的第二次尝试非常接近原则性解决方案。正如您所观察到的,问题是在实现 BW a 时不能将类型 a 作为参数。但是你不在乎,因为你以后总是可以显式地设置一个隐式参数。

这给了我们:

interface BW a where
  byteWidth_ : Int

implementation BW Int where
  byteWidth_ = 8

implementation BW Char where
  byteWidth_= 1

然后您可以通过部分应用 byteWidth_ 来恢复您想要的类型,如下所示:

byteWidth : (a : Type) -> BW a => Int
byteWidth a = byteWidth_ {a}