Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.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
Scala F[A]和A之间的区别是什么?_Scala_Haskell_Types - Fatal编程技术网

Scala F[A]和A之间的区别是什么?

Scala F[A]和A之间的区别是什么?,scala,haskell,types,Scala,Haskell,Types,对于Scala和Haskell等语言,可以使用类型构造函数构造类型。区分所有这些部分的正确词汇是什么 A是一种类型F[A]也是一种类型。有没有语言可以区分这两者 什么是A 什么是F[A] 什么是F?在Scala中不知道,但在Haskell中,报告确实区分了两个语法类别:“类型”和“构造函数”。构造函数就是那些单原子类型,以大写字母开头,由data和newtype声明创建。e、 g data Foo a = Bar 创建一个新的类型构造函数Foo(和一个新的数据构造函数Bar),可以通过将Foo

对于Scala和Haskell等语言,可以使用类型构造函数构造类型。区分所有这些部分的正确词汇是什么

A
是一种类型
F[A]
也是一种类型。有没有语言可以区分这两者

什么是
A

什么是
F[A]


什么是
F

在Scala中不知道,但在Haskell中,报告确实区分了两个语法类别:“类型”和“构造函数”。构造函数就是那些单原子类型,以大写字母开头,由
data
newtype
声明创建。e、 g

data Foo a = Bar
创建一个新的类型构造函数
Foo
(和一个新的数据构造函数
Bar
),可以通过将
Foo
应用到另一个类型来形成类型。当然,建设者不必是更高级的
data Baz=qux
还声明了名为
Baz
的类型构造函数,该构造函数不允许应用于任何其他类型

(但请注意:通常使用“类型构造函数”来表示“任何带有箭头类型的类型级表达式”,因此,如果您正在进行一些技术写作,您应该在介绍中包含一些文本,以澄清您打算在本文档的其余部分中使用这两种含义中的哪一种。)

因此,在您的示例中,我们可以说
Map
是一个构造函数,
Char
是一个构造函数,
Int
是一个构造函数,
Map Char
是一个类型,
Map Char Int
是一个类型


据我所知,这些类别中的任何一个都没有通用的速记词:“绝对不是构造函数的类型”、“绝对不是构造函数的类型”、“绝对不是构造函数的类型”。对于允许应用于另一种类型的类型,有术语“高级类型”——例如
Map
Map Char
都是高级类型。

注释中提到的技术术语是“类型”、“某些其他类型”和“类型构造函数”

考虑:

 data A = A
  --  ^   ^--- The Data Constructor
  --  -- The type

data F   x = SomeDataConstructorForF x
 --  ^   ^     ^-- Data Constr       ^-- Field
 --  |   --- Type Variable
 --  - Type Constructor

val :: A
val = A
-- A value of type 'A'

val2 :: F [A]
val2 = SomeDataConstructorForF []
-- A value of some other type, F [A].
-- No special term exists for types built through application
-- of one or more type constructor afaik

我建议只调用
F[A]
类型构造函数的
F[A]应用程序
F
类型的
*->*
参数
A
类型的
。来自规范,而“应用程序”来自基本的lambda演算,如下所述

回想当年的形式主义

这意味着您有以下形成种类的规则:

  • *
    是一种
  • 如果
    a
    b
    是种类,那么
    a->b
    就是种类
  • 您可以按如下方式形成术语:

  • 具有固定种类的预定义常量是术语
  • 变量是术语
  • 如果
    f
    a
    是术语,则应用程序
    f a
    是术语
  • 如果
    x
    是一个变量名,
    y
    是一个术语,那么抽象
    \x.y
    就是一个术语
  • 您可以检查(类型值)术语是否与如下规则相匹配:

  • 类型为
    k
    (真空)的预定义常量
    c
    具有类型
    k
    ,而与上下文无关
  • 如果上下文
    Gamma
    包含变量
    v
    到种类
    k
    的映射,那么在
    Gamma
    中,我们可以推断
    v
    是种类
    k
    的一个良好的表达式
  • 如果在上下文
    Gamma
    中,我们可以推断
    f
    具有种类
    a->b
    并且
    x
    具有种类
    a
    ,那么应用程序
    fx
    具有种类
    b
  • 如果在上下文
    Gamma中,x:a
    我们可以推断
    y
    具有种类
    b
    ,那么在
    Gamma
    中,我们可以推断
    \x.y
    具有种类
    a->b
  • 我看不出有任何理由发明任何新词汇,所以我只使用“应用程序”


    旁白:你实际上可以很快地写下以上基本的推理算法

    sealed trait Term
    case class Apply(func: Term, arg: Term) extends Term
    case class Lam(preferred: String, dom: Type, body: Term) extends Term
    
    case class BoundVar(deBruijnIdx: Int) extends Term
    case class FreeVar(name: String) extends Term
    
    sealed trait Type
    case object * extends Type
    case class Func(dom: Type, cod: Type) extends Type {
      override def toString = s"($dom -> $cod)"
    }
    
    import util.{Either, Left, Right}
    
    case class Ctx(globalConstants: Map[String, Type], stack: List[Type]) {
      def push(tp: Type): Ctx = Ctx(globalConstants, tp :: stack)
      def pop: Ctx = Ctx(globalConstants, stack.tail)
    }
    
    object Ctx {
      def empty = Ctx(Map.empty, List.empty)
      def emptyWithGlobals(keys: (String, Type)*) = Ctx(keys.toMap, Nil)
    }
    
    def tinf(t: Term, ctx: Ctx = Ctx.empty): Either[String, Type] = t match {
      case FreeVar(v) => 
        ctx.globalConstants.get(v).map(Right(_)).getOrElse(Left("Undefined: " + v))
      case BoundVar(d) => Right(ctx.stack(d))
      case Apply(f, x) => 
        for {
          tf <- tinf(f, ctx)
          tx <- tinf(x, ctx)
          res <- tf match {
            case Func(a, b) =>
              if (tx == a) Right(b)
              else Left(s"Type mismatch: cannot apply `$a` to `$b`")
            case sthElse => Left(s"Not applicable: $sthElse")
          }
        } yield res
      case Lam(_, tp, b) => 
        for {
          tb <- tinf(b, ctx.push(tp))
        } yield Func(tp, tb)
    }
    
    for {
      example <- List(
        Lam("x", *, BoundVar(0)),
        Lam("x", *, Lam("y", Func(*, *), Apply(BoundVar(0), BoundVar(1))))
      )
    } println(example + " : " + tinf(example))
    
    有那种

    (* -> *)
    (* -> ((* -> *) -> *))
    

    分别。

    AFAIK对于
    F[A]
    没有明显的标准区别术语,因为它不是一个特别有用的区别
    A
    F[A]
    是类型,
    F
    是类型构造函数。我会借用函数中的术语。在
    F[A]
    中,
    A
    是参数,
    F[A]
    可能是结果,
    F
    是类型构造函数。有时候,它是上下文的,但是如果你举一个或两个例子,我可能会更有帮助。“不是所有类型的构造函数都是函子”。考虑两种类型的构造函数:代码> NeXType F f= f(f(f f))< /> >和<代码>数据nf a= z<a</c>。您认为更复杂的是:类型<代码> f nf<代码>还是类型<代码>整数< /代码>?(当然,这两种类型是不等价的,但它表明,您所讨论的复杂性与实现的关系比结果类型的任何基本属性都更密切。)@MarkCanlas
    5
    是一个带值的表达式,
    5+2
    也是一个带值的表达式;同样地,对于某些适当的函数
    f
    。它们不需要特殊的名称来表示一个是函数调用的结果,一个是文本;它们只是价值观。同样,在类型级别,独立类型和通过将类型构造函数应用于某些类型参数而生成的类型是相同的,无论您如何生成它们。什么是“报告”?@MarkCanlas the Haskell Language Report,很容易用谷歌搜索:当你说
    Char
    是一个构造函数,
    Int
    是一个构造函数时,你能进一步说明你的意思吗?这听起来有悖常理。@MarkCanlas
    Char
    Int
    是类型构造函数吗?一旦你有了整个苹果
    (* -> *)
    (* -> ((* -> *) -> *))