简体   繁体   English

构造函数内部和构造函数外部的 forall 量词之间的区别

[英]Difference between forall quantifier inside a constructor and outside a constructor

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}

import Data.Proxy

data Foo = FooA | FooB

class Bar (a :: k) where
    bar :: Proxy a -> Int

instance Bar FooA where
    bar _ = 1

instance Bar FooB where
    bar _ = 2

foo1 :: forall (a :: Foo). Proxy a -> (Bar a => Proxy a)
foo1 p = p

data BarProxy = BarProxy (forall a. Bar a => Proxy a)

foo2 :: forall (a :: Foo). Proxy a -> BarProxy
foo2 p = BarProxy (foo1 p)

main = print "Hello World"

In this code:在这段代码中:

  1. Doesn't foo1 , given any Proxy a where a is of kind Foo , return a Proxy a such that a has an instance of Bar ?是否foo1 ,给定任何Proxy a ,其中aFoo ,返回一个Proxy a使得a具有Bar的实例?
  2. Doesn't BarProxy constructor accept any Proxy a , where a has an instance of Bar ? BarProxy构造函数不接受任何Proxy a ,其中a有一个Bar实例? How is it different from data BarProxy = forall a. BarProxy (Bar a => Proxy a)data BarProxy = forall a. BarProxy (Bar a => Proxy a)有什么区别data BarProxy = forall a. BarProxy (Bar a => Proxy a) data BarProxy = forall a. BarProxy (Bar a => Proxy a) ? data BarProxy = forall a. BarProxy (Bar a => Proxy a) ?
  3. Why does foo2 p = BarProxy (foo1 p) fail with the below error?为什么foo2 p = BarProxy (foo1 p)失败并出现以下错误?
Test6.hs:27:20: error:
    • Couldn't match type ‘a1’ with ‘a’
      ‘a1’ is a rigid type variable bound by
        a type expected by the context:
          forall (a1 :: Foo). Bar a1 => Proxy a1
        at Test6.hs:27:10-26
      ‘a’ is a rigid type variable bound by
        the type signature for:
          foo2 :: forall (a :: Foo). Proxy a -> BarProxy
        at Test6.hs:26:1-46
      Expected type: Proxy a1
        Actual type: Proxy a
    • In the first argument of ‘BarProxy’, namely ‘(foo1 p)’
      In the expression: BarProxy (foo1 p)
      In an equation for ‘foo2’: foo2 p = BarProxy (foo1 p)
    • Relevant bindings include
        p :: Proxy a (bound at Test6.hs:27:6)
        foo2 :: Proxy a -> BarProxy (bound at Test6.hs:27:1)
   |
27 | foo2 p = BarProxy (foo1 p)
   |                    ^^^^^^
  1. No. My understanding is that the signature of foo1 is the same as forall (a :: Foo). Bar a => Proxy a -> Proxy a不。我的理解是foo1的签名与forall (a :: Foo). Bar a => Proxy a -> Proxy a forall (a :: Foo). Bar a => Proxy a -> Proxy a (though I couldn't find any document). forall (a :: Foo). Bar a => Proxy a -> Proxy a (虽然我找不到任何文件)。 In ghci, :t foo1 gives foo1 :: Bar a => Proxy a -> Proxy a .在 ghci 中, :t foo1给出foo1 :: Bar a => Proxy a -> Proxy a Given any Proxy a where a is of kind Foo and an instance of Bar , it returns Proxy a .给定任何Proxy a ,其中aFoo类型和Bar一个实例,它返回Proxy a

  2. No. The constructor BarProxy has rank-2 polymorphic type (forall a. Bar a => Proxy a) -> BarProxy .不。构造函数BarProxy具有 rank-2 多态类型(forall a. Bar a => Proxy a) -> BarProxy This means that an argument p can be passed to BarProxy only if p has the type Proxy a for all type a which is an instance of Bar .这意味着只有当p具有类型Proxy a所有类型a它是Bar的实例)时,参数p才能传递给BarProxy If you want existentially quantified one, you may write如果你想要存在量化的一个,你可以写

    data BarProxy = forall a. Bar a => BarProxy (Proxy a)

    or或者

    data BarProxy where BarProxy :: forall a. Bar a => Proxy a -> BarProxy

    with -XGADTs enabled.启用-XGADTs

    Let us call BarProxy of type forall a. Bar a => Proxy a -> BarProxy让我们调用forall a. Bar a => Proxy a -> BarProxy类型的BarProxy forall a. Bar a => Proxy a -> BarProxy forall a. Bar a => Proxy a -> BarProxy existential BarProxy and that of type (forall a. Bar a => Proxy a) -> BarProxy universal BarProxy . forall a. Bar a => Proxy a -> BarProxy存在性BarProxy和类型(forall a. Bar a => Proxy a) -> BarProxy通用BarProxy For existential one, the argument p should have type either Proxy FooA or Proxy FooB (existentially quantified over {a | a is an instance of Bar} = {FooA,FooB} ).为存在一个,参数p的类型应该是任何Proxy FooAProxy FooB (存在上定量比{a | a is an instance of Bar} = {FooA,FooB} For universal one, on the other hand, p should have type both Proxy FooA and Proxy FooB (universally quantified over the same set).另一方面,对于通用的, p应该同时具有Proxy FooAProxy FooB (在同一集合上普遍量化)。 Let us consider three proxies below.让我们考虑下面的三个代理。

     proxyFooA :: Proxy FooA proxyFooA = Proxy proxyFooB :: Proxy FooB proxyFooB = Proxy proxyPoly :: forall a. Proxy a proxyPoly = Proxy

    Existential BarProxy accepts any of the three while universal one accepts only proxyPoly . Existential BarProxy接受三者中的任何一个,而通用proxyPoly只接受proxyPoly

  3. foo2 p = BarProxy (foo1 p) compiles for existential BarProxy . foo2 p = BarProxy (foo1 p)为存在的BarProxy编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在上下文中使用数据构造函数 - forall in Context with Data constructor forall a之间有什么区别? [a]和[forall a。一个]? - What is the difference between forall a. [a] and [forall a. a]? 是否有可能'解决'一个量词量词? - Is it possible to 'uncurry' a forall quantifier? 在haskell中使用forall量词的谓词? - Predicate with forall quantifier in haskell? 可以在模式匹配中交换构造函数的通用和存在量词吗? - Can a universal and existential quantifier for a constructor be commuted in pattern matching? Doc数据值构造函数Char和Text之间的区别 - Difference between Doc data value constructor Char and Text monad 的类型构造函数和返回函数之间的区别(在 Haskell 中) - Difference between type constructor and return function of a monad (in Haskell) 理解两个Haskell签名之间的区别,一个使用forall - Understanding the difference between two Haskell signatures, one using forall 在Hedgehog中通过'Gen'或'forAll'生成随机输入之间的区别 - Difference between generating random input through 'Gen' or through 'forAll' in Hedgehog Either和Either Int有什么区别?什么是A?多态类型构造函数?它的目的是什么? - What is the difference between Either a and Either Int? What is Either a ? A polymorphic type constructor? What is its purpose?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM