Haskell 类型级别文字 Nat:状态?
Haskell type level literal Nat: status?
GHC 具有类型级别文字 Nats。我可以阅读一些关于它们的信息,例如,在这里:
https://ghc.haskell.org/trac/ghc/wiki/TypeNats
不幸的是,关于它们的文档似乎很少,而且我尝试用它们做的几乎没有任何实际效果。
来自 this page 的评论 18 提到了这个大小参数化 Vecs 的简单示例(我添加了 LANGUAGE pragmas 和导入语句):
{-# 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 应该可用于这种事情吗?如果是这样,我如何实现 (+++) 功能?如果不是,他们的用例是什么?
正如评论者所提到的,类型检查器目前无法解除这种等式,因为它们需要代数。尽管你我都知道 n + m = n1 + m + 1
给定 n = n1 + 1
,但没有人教过 GHC 类型检查器如何执行那种算术。在像 Ada、Idris 或 Coq 这样的语言中,您可以教编译器这些规则,或者算术规则可能会在库中提供给您,但在 Haskell 中,类型检查器更加严格(但在我看来,这对现实世界的编程更友好),不幸的是你不得不求助于类型检查器插件。
据我所知,在这个问题上最积极的人是 Iavor Diatchki. That paper is behind the dumb ACM paywall, but you can find his Haskell Symposium 2015 talk here on YouTube — it's very well-explained!. His talk uses the same example as yours, the ever-popular vector. His branch in the GHC repository works on merging it into mainline GHC, but as far as I know there are no dates set. For now you have to use the typechecker plugin, which is not so bad. After all, the original goal of Plugins/Typechecker 是为了启用这样有趣的工作,而不必将所有内容合并到源代码中。模块化有话要说!
GHC 具有类型级别文字 Nats。我可以阅读一些关于它们的信息,例如,在这里:
https://ghc.haskell.org/trac/ghc/wiki/TypeNats
不幸的是,关于它们的文档似乎很少,而且我尝试用它们做的几乎没有任何实际效果。
来自 this page 的评论 18 提到了这个大小参数化 Vecs 的简单示例(我添加了 LANGUAGE pragmas 和导入语句):
{-# 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 应该可用于这种事情吗?如果是这样,我如何实现 (+++) 功能?如果不是,他们的用例是什么?
正如评论者所提到的,类型检查器目前无法解除这种等式,因为它们需要代数。尽管你我都知道 n + m = n1 + m + 1
给定 n = n1 + 1
,但没有人教过 GHC 类型检查器如何执行那种算术。在像 Ada、Idris 或 Coq 这样的语言中,您可以教编译器这些规则,或者算术规则可能会在库中提供给您,但在 Haskell 中,类型检查器更加严格(但在我看来,这对现实世界的编程更友好),不幸的是你不得不求助于类型检查器插件。
据我所知,在这个问题上最积极的人是 Iavor Diatchki. That paper is behind the dumb ACM paywall, but you can find his Haskell Symposium 2015 talk here on YouTube — it's very well-explained!. His talk uses the same example as yours, the ever-popular vector. His branch in the GHC repository works on merging it into mainline GHC, but as far as I know there are no dates set. For now you have to use the typechecker plugin, which is not so bad. After all, the original goal of Plugins/Typechecker 是为了启用这样有趣的工作,而不必将所有内容合并到源代码中。模块化有话要说!