代码之家  ›  专栏  ›  技术社区  ›  riccardo.cardin

在函数式编程语言中,类型构造器可以被视为类型吗?

  •  7
  • riccardo.cardin  · 技术社区  · 6 年前

    我正在接近Haskell编程语言,我有斯卡拉和Java开发人员的背景。

    我正在阅读类型构造器背后的理论,但是我不理解它们是否可以被视为类型。我的意思是,在scala中,你使用关键字 class trait 定义类型构造函数。考虑 List[T] Option[T] . 同样在haskell中,您使用相同的关键字 data ,用于定义新类型。

    那么,类型构造函数也是类型吗?

    3 回复  |  直到 6 年前
        1
  •  6
  •   Jörg W Mittag    6 年前

    让我们来看一个类比:函数。在数学的某些分支中,函数被称为 值构造函数 因为这就是他们所做的:你输入一个或多个值,然后他们从中构造一个新的值。

    类型构造函数完全相同,除了类型级别:您放入一个或多个类型,然后它们从中构造一个新类型。在某种意义上,它们是类型级别上的函数。

    现在,与我们的类比:你所问问题的类比是什么?好吧,它是这样的:“在函数编程语言中,值构造器(即函数)能被视为值吗?”

    答案是:这取决于编程语言。现在,对于函数式编程语言,几乎所有(如果不是全部)语言的答案都是“是”。这取决于你对“函数式编程语言”的定义。有些人将函数式编程语言定义为一种具有值函数的编程语言,因此根据定义,答案将是微不足道的“是”。但是,有些人将函数式编程语言定义为不允许副作用的编程语言,在这种语言中,函数不一定是值。

    最著名的例子可能是约翰·巴克斯的《外交政策》,来自他的开创性论文。 编程能从冯·诺依曼风格中解放出来吗?函数式及其程序代数 . 在FP中,有一个“类似功能”的层次结构。函数只能处理值,而函数本身不是值。然而,“功能”的概念是“功能构造器”,即它们可以将功能(以及值)作为输入和/或生成函数作为输出,但不能将功能作为输入和/或生成函数作为输出。

    因此,fp可以说是一种函数式编程语言,但它没有函数作为值。

    注:函数值也称为“一级函数”,将函数作为输入或作为输出返回的函数称为“高阶函数”。

    如果我们看一些类型:

    1   :: Int
    [1] :: List Int
    add :: Int → Int
    map :: (a → b, List a) → b
    

    您可以看到,我们可以很容易地说:任何类型中有箭头的值都是一个函数。任何类型中有多个箭头的值都是高阶函数。

    同样,这同样适用于类型构造函数,因为它们实际上是相同的,除了在类型级别上。在某些语言中,类型构造函数可以是类型,在某些语言中它们不能。例如,在Java和C中,类型构造函数不是类型。你不能有 List<List> 例如,在C中。你可以 记下 类型 列表<列表> 在Java,但这是误导性的,因为这两个 List 意思不同:第一个 是类型构造函数,第二个 原始类型 ,所以这实际上是 使用类型构造函数作为类型。

    与上面的类型示例等效的是什么?

    Int     :: Type
    List    :: Type ⇒ Type
    →       :: (Type, Type) ⇒ Type
    Functor :: (Type ⇒ Type) ⇒ Type
    

    (注意,我们总是 Type ?实际上,我们只处理类型,所以通常不写 类型 而是简单地写 * ,发音为“type”):

    Int     :: *
    List    :: * ⇒ *
    →       :: (*, *) ⇒ *
    Functor :: (* ⇒ *) ⇒ *
    

    所以, Int 是一个合适的类型, 是采用一种类型并生成一种类型的类型构造函数, → (函数类型构造函数)接受两个类型并返回一个类型(仅假定一元函数,例如使用currying或传递元组),以及 Functor 是类型构造函数,它本身接受类型构造函数并返回类型。

    这些“类型类型”被称为 种类 . 与函数一样,任何带有箭头的对象都是类型构造函数,任何带有多个箭头的对象都是 高级类构造函数 .

    和函数一样,有些语言允许更高类型的构造函数,有些不允许。您在问题中提到的两种语言scala和haskell 但是,正如上面提到的,Java和C没有。

    但是,当我们看到您的问题时,会有一个复杂的问题:

    那么,类型构造函数也是类型吗?

    不,不,至少我不懂任何语言。请参见,虽然您可以拥有更高类型的构造函数,这些构造函数将类型构造函数作为输入和/或返回它们作为输出,但您不能拥有表达式、值、变量或参数,这些表达式、值、变量或参数的类型都是类型构造函数。不能有一个函数需要 或返回 . 不能有类型为的变量 Monad . 但是,你 可以 具有类型的变量 int .

    因此,很明显,类型和类型构造函数之间存在差异。

        2
  •  6
  •   madgen    6 年前

    好吧,类型和类型构造器有自己的微积分,它们都有类型。如果你使用 :k (Maybe Int) 在里面 ghci 例如,你会 * ,现在这是一个合适的类型( 通常 )有居民。在这种情况下 Nothing , Just 42 等。 * 现在有了更具描述性的别名 Type .

    现在,您可以看到构造函数的类型 Maybe :k Maybe 会给你 * -> * . 对于别名,这是 Type -> Type 这就是你所期望的。它需要一个 类型 建构 类型 . 现在,如果您将类型视为一组值,那么一个好问题是值的作用是什么 也许吧 有?嗯,没有,因为它不是真正的类型。你可能会尝试 Just 但那有类型 a -> Maybe a 用实物 类型 而不是 也许吧 用实物 类型-GT型 .

        3
  •  3
  •   leftaroundabout    6 年前

    至少在Haskell中,有一个可以大致描述如下的层次结构。

    条款 是在运行时存在的东西,比如 1 , 'a' (+) 例如。

    每个词都有 类型 ,像 Int Char Int -> Int -> Int .

    每种类型都有 友善的 所有类型都有相同的类型,即 * .

    类型构造函数 [] 尽管如此,还是有点 * -> * ,因此它不是类型。相反,它是一个 映射 从类型到类型。


    还有其他种类,包括 * * & gt;* ,各有一个例子):

    • * -> * -> * ( Either )
    • (* -> *) -> * -> * ( ReaderT (一台单体变压器)
    • Constraint ( Num Int )
    • * -> Constraint ( Num ;这是一种类型类)