Ran*_*ala 14 haskell gadt dependent-type singleton-type
我希望一些Haskell专家可以帮助澄清一些事情.
是否有可能以Nat
通常的方式定义(通过Haskell中的 @dorchard Singleton类型)
data S n = Succ n
data Z = Zero
class Nat n
instance Nat Z
instance Nat n => Nat (S n)
Run Code Online (Sandbox Code Playgroud)
(或其一些变体)然后定义一个LessThan
关系,使得forall n
和m
LessThan Z (S Z)
LessThan n m => LessThan n (S m)
LessThan n m => LessThan (S n) (S m)
Run Code Online (Sandbox Code Playgroud)
然后编写一个类似的函数:
foo :: exists n. (LessThan n m) => Nat m -> Nat n
foo (S n) = n
foo Z = foo Z
Run Code Online (Sandbox Code Playgroud)
我明确地想在输出类型中使用"LessThan" foo
,我意识到人们肯定会写出类似的东西
foo :: Nat (S n) -> Nat n
Run Code Online (Sandbox Code Playgroud)
但那不是我追求的.
谢谢!
兰吉特.
Tox*_*ris 17
这是实现类似于您所询问的内容的一种方法.
首先请注意,您将其定义Nat
为类,然后将其用作类型.我认为将它作为一种类型是有道理的,所以让我们这样定义它.
data Z
data S n
data Nat n where
Zero :: Nat Z
Succ :: Nat n -> Nat (S n)
Run Code Online (Sandbox Code Playgroud)
我们也可以定义LessThan
为一种类型.
data LessThan n m where
LT1 :: LessThan Z (S Z)
LT2 :: LessThan n m -> LessThan n (S m)
LT3 :: LessThan n m -> LessThan (S n) (S m)
Run Code Online (Sandbox Code Playgroud)
请注意,我只是将您的三个属性转换为数据构造函数.这种类型的想法是类型的完全标准化值是小于LessThan n m
的证明.n
m
现在你问:
foo :: exists n. (LessThan n m) => Nat m -> Nat n
Run Code Online (Sandbox Code Playgroud)
但是Haskell中不存在.相反,我们可以为以下内容定义数据类型foo
:
data Foo m where
Foo :: Nat n -> LessThan n m -> Foo m
Run Code Online (Sandbox Code Playgroud)
请注意,n
这里有效地存在量化,因为它显示在数据构造函数的参数中,Foo
但不显示在其结果中.现在我们可以说出以下类型foo
:
foo :: Nat m -> Foo m
Run Code Online (Sandbox Code Playgroud)
在我们从问题中实现示例之前,我们必须证明一个小问题LessThan
.引理说这n
比S n
所有人都要少n
.我们通过归纳证明了这一点n
.
lemma :: Nat n -> LessThan n (S n)
lemma Zero = LT1
lemma (Succ n) = LT3 (lemma n)
Run Code Online (Sandbox Code Playgroud)
现在我们可以从问题中编写代码:
foo :: Nat m -> Foo m
foo (Succ n) = Foo n (lemma n)
foo Zero = foo Zero
Run Code Online (Sandbox Code Playgroud)