簡體   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"

在這段代碼中:

  1. 是否foo1 ,給定任何Proxy a ,其中aFoo ,返回一個Proxy a使得a具有Bar的實例?
  2. BarProxy構造函數不接受任何Proxy a ,其中a有一個Bar實例? 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. 為什么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. 不。我的理解是foo1的簽名與forall (a :: Foo). Bar a => Proxy a -> Proxy a forall (a :: Foo). Bar a => Proxy a -> Proxy a (雖然我找不到任何文件)。 在 ghci 中, :t foo1給出foo1 :: Bar a => Proxy a -> Proxy a 給定任何Proxy a ,其中aFoo類型和Bar一個實例,它返回Proxy a

  2. 不。構造函數BarProxy具有 rank-2 多態類型(forall a. Bar a => Proxy a) -> BarProxy 這意味着只有當p具有類型Proxy a所有類型a它是Bar的實例)時,參數p才能傳遞給BarProxy 如果你想要存在量化的一個,你可以寫

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

    或者

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

    啟用-XGADTs

    讓我們調用forall a. Bar a => Proxy a -> BarProxy類型的BarProxy forall a. Bar a => Proxy a -> BarProxy forall a. Bar a => Proxy a -> BarProxy存在性BarProxy和類型(forall a. Bar a => Proxy a) -> BarProxy通用BarProxy 為存在一個,參數p的類型應該是任何Proxy FooAProxy FooB (存在上定量比{a | a is an instance of Bar} = {FooA,FooB} 另一方面,對於通用的, p應該同時具有Proxy FooAProxy FooB (在同一集合上普遍量化)。 讓我們考慮下面的三個代理。

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

    Existential BarProxy接受三者中的任何一個,而通用proxyPoly只接受proxyPoly

  3. foo2 p = BarProxy (foo1 p)為存在的BarProxy編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM