Haskell类型级文字Nat:状态?

时间:2015-08-10 11:31:53

标签: haskell dependent-type

GHC有类型级文字Nats。我可以阅读一些关于它们的内容,例如:

https://ghc.haskell.org/trac/ghc/wiki/TypeNats

不幸的是,似乎没有关于它们的文档,我尝试用它们几乎没有任何实际工作。

来自this page的评论18提到了这个大小参数化Vecs的简单示例(我添加了LANGUAGE编译指示和导入语句):

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}

import GHC.TypeLits

data Vec :: Nat -> * -> * where
  Nil  :: Vec 0 a
  (:>) :: a -> Vec n a -> Vec (n+1) a

(+++) :: Vec n a -> Vec m a -> Vec (n+m) a
Nil       +++ bs = bs
(a :> as) +++ bs = a :> (as +++ bs)

当时没有工作,但是后来应该修改实现以便这样做。那是5年前......但它不适用于我的GHC 7.10.1:

trash.hs:15:20:
    Could not deduce ((n + m) ~ ((n1 + m) + 1))
    from the context (n ~ (n1 + 1))
      bound by a pattern with constructor
                 :> :: forall a (n :: Nat). a -> Vec n a -> Vec (n + 1) a,
               in an equation for ‘+++’
      at trash.hs:15:2-8
    NB: ‘+’ is a type function, and may not be injective
    Expected type: Vec (n + m) a
      Actual type: Vec ((n1 + m) + 1) a
    Relevant bindings include
      bs :: Vec m a (bound at trash.hs:15:15)
      as :: Vec n1 a (bound at trash.hs:15:7)
      (+++) :: Vec n a -> Vec m a -> Vec (n + m) a
        (bound at trash.hs:14:1)
    In the expression: a :> (as +++ bs)
    In an equation for ‘+++’: (a :> as) +++ bs = a :> (as +++ bs)

这是什么交易?类型级文字Nats应该可用于此类事情吗?如果是这样,我该如何实现(+++)函数?如果没有,他们的用例是什么?

1 个答案:

答案 0 :(得分:4)

正如评论者所提到的,类型检查者目前无法解除这种平等,因为它们需要代数。虽然你和我知道n + m = n1 + m + 1给出n = n1 + 1,但没有人教过GHC类型检查器如何执行这种算术。在像Ada,Idris或Coq这样的语言中,您可以向编译器传授这些规则,或者可能会在库中提供算术规则,但在Haskell中,类型检查器更加严格(但更友好)在我看来,对于真实世界的编程而言,你不得不求助于一个类型检测器插件。

我所知道的最积极解决此问题的人是Iavor Diatchki。那篇论文背后是愚蠢的ACM付费专栏,但是你可以找到他的Haskell Symposium 2015 talk here on YouTube - 这是非常好的解释!他的演讲使用与你的相同的例子,这是一个非常受欢迎的矢量。 His branch in the GHC repository致力于将其合并到主线GHC中,但据我所知,没有设定日期。现在你必须使用typechecker插件,这并不是那么糟糕。毕竟,原始的goal of Plugins/Typechecker是为了实现这样有趣的工作,而不必将所有内容合并到源代码中。模块化有一些东西可以说!