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应该可用于此类事情吗?如果是这样,我该如何实现(+++)函数?如果没有,他们的用例是什么?
答案 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是为了实现这样有趣的工作,而不必将所有内容合并到源代码中。模块化有一些东西可以说!