Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 理解“GHC.TypeLits”`_Haskell_Ghc - Fatal编程技术网

Haskell 理解“GHC.TypeLits”`

Haskell 理解“GHC.TypeLits”`,haskell,ghc,Haskell,Ghc,我正试图对GHC扩展KindSignatures和datatypes了如指掌。从包装上看,我大致明白这一点 newtype i `Mod` (n :: Nat) = Mod i deriving (Eq, Ord) 类似于声明C++模板 (构造函数只使用一个类型的代码 t>代码>。然而,看着这个包裹,我不明白发生了什么。任何关于此包的一般性解释都会有所帮助。在这个问题被标记为离题之前,这里有一些具体的子问题: KnownNat类是有意义的,所需的函数允许您从类型中提取类型变量,但是natVa

我正试图对GHC扩展
KindSignatures
datatypes
了如指掌。从包装上看,我大致明白这一点

newtype i `Mod` (n :: Nat) = Mod i deriving (Eq, Ord)
类似于声明C++模板<代码> <代码>(构造函数只使用一个类型的代码<代码> t>代码>。然而,看着这个包裹,我不明白发生了什么。任何关于此包的一般性解释都会有所帮助。在这个问题被标记为离题之前,这里有一些具体的子问题:

  • KnownNat
    类是有意义的,所需的函数允许您从类型中提取类型变量,但是
    natVal
    做什么,以及
    proxy
    类型变量是什么
  • 您将在哪里使用
    someNatVal
  • 最后,什么是
    SomeNat
    ——类型级别号怎么可能是未知的?在编译时,类型级别编号的整个点不就是已知的吗

    • 这个问题相当广泛——我只讲几点

      代理
      类型变量只是
      *->*
      类型的类型变量,即类型构造函数的类型。实际上,如果你有一个功能

      foo :: proxy a -> ...
      
      bar :: N -> ...
      
      您可以将类型为的值传递给它,例如
      Maybe Int
      ,选择
      proxy=Maybe
      a=Int
      。您还可以传递类型为
      []Char
      (也称为
      [Char]
      )的值。或者,更常见的是,类型为
      Proxy Int
      的值,其中
      Proxy
      是定义为

      data Proxy a = Proxy
      
      i、 e.一种数据类型,它不携带任何运行时信息(只有一个值!),但携带编译时信息(幻象类型变量
      a

      假设
      N
      是一种
      Nat
      ——编译时自然语言。我们可以写一个函数

      foo :: proxy a -> ...
      
      bar :: N -> ...
      
      但是调用它需要我们构建一个
      N
      类型的值——这是无关紧要的。类型
      N
      的目的只是携带编译时信息,它的运行时值不是我们真正想要使用的东西。事实上,
      N
      可能根本没有值,除了底部。我们可以打电话

      但这看起来很奇怪。阅读本文,我们必须意识到,
      bar
      在其第一个参数中是懒惰的,并且在尝试使用它时不会引起分歧。问题在于,
      bar::N->…
      类型签名具有误导性:它声称结果可能取决于
      N
      类型的参数值,而实际情况并非如此。相反,如果我们使用

      baz :: Proxy N -> ...
      
      意图很清楚——只有一个运行时值:
      Proxy::Proxy N
      。同样清楚的是,
      N
      值只在编译时出现

      有时,代码不是使用特定的
      代理N
      ,而是稍微泛化为

      foo :: proxy N -> ...
      
      它实现了相同的目标,但也允许不同的
      代理
      类型。(就我个人而言,我对这一概括并不感到非常激动。)

      回到问题:
      natVal
      是一个函数,它将编译时纯自然值转换为运行时值。也就是说,它将
      Proxy N
      转换为
      Int
      ,只返回常量

      <>你如果使用类型模板参数来编译编译时间自然,你可以更接近C++模板。例如

      模板结构{使用pred=N;};
      结构Z{};
      模板int natVal();
      模板int natVal(){return 1+natVal();}
      template int natVal(){return 0;}
      int main(){
      
      使用代理的一个重要原因可能是,您试图传递的类型级别
      a
      可能没有种类
      *
      。例如,
      proxy 3->b
      很相似,但是
      3->b
      不相似;
      proxy Maybe->b
      很相似,但是
      Maybe->b
      不相似。此外,
      未定义::N
      只有在N有kind*时才是好的kind。不,类型不必在编译时都知道。例如,在编译
      id
      时,不知道所有可能的参数都是什么。@奥古斯特的观点很好,但是
      SomeNat
      的目的是什么?它是一个存在量化类型的类型。你知道它是一种Nat,但不确切是哪种类型。