簡體   English   中英

為什么 GHC 拒絕允許這種存在類型函數?

[英]Why does GHC refuse to allow this existential type function?

我已經定義了一個通用的heterogenous ,我稱之為(我不知道這是否正確),輸入:

data Heterotype f = forall a. f a => Heterotype a

然后我決定創建一個函數,允許您從多態值創建異型:

hset :: (forall a. f a => a) -> Heterotype f
hset x = Heterotype x

但是,GHC 抱怨以下內容:

████████.hs:15:10: error:
    * Could not deduce: f a0 arising from a use of `Heterotype'
    * In the expression: Heterotype x
      In an equation for `hset': hset x = Heterotype x
    * Relevant bindings include
        x :: forall a. f a => a
          (bound at ████████.hs:15:6)
        hset :: (forall a. f a => a) -> Heterotype f
          (bound at ████████.hs:15:1)
   |
15 | hset x = Heterotype x
   |          ^^^^^^^^^^^^

編輯:啟用以下擴展:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
{-# LANGUAGE NoStarIsType, ConstraintKinds #-}
{-# LANGUAGE AllowAmbiguousTypes, RankNTypes #-}
import Data.Kind

從邏輯的角度來看,您的代碼將對應於邏輯公式的證明,可以如下(粗略地)閱讀:

  • f是任何類型的屬性;
  • 假設,對於滿足f任何類型a ,我們可以產生類型a的值x
  • 那么,存在滿足f且值為x的類型a

這在邏輯上是不合理的。 事實上,無論a是什么, fa都可能永遠不成立。 在這種情況下,上面的假設空洞地成立,因此它是正確的。 然而,上述結論與fa總是錯誤的事實相矛盾。

因此,我們無法使用該類型定義您的hset

為了使論證合理,我們必須添加一個額外的假設,即存在某種類型b使屬性f真。 如果我們加上這個假設,我們可以證明這個陳述:

-- (untested, but should work)
hset :: forall b . f b => (forall a. f a => a) -> Heterotype f
hset x = Heterotype (x :: b)

您的數據定義隱藏的monotyped選擇a被包裝起來,從詞典的價值f 重要的是要認識到,這樣做的全部意義在於丟棄有關特定類型的信息,同時保留與該類型關聯的實例字典。

這與您在hset嘗試執行的操作不hset 從來沒有一個具體的類型來打包實例。 這些部分不能以這種方式組合在一起,因為它們都缺少相同的必需的東西。 Heterotype f(forall a. fa => a)都缺乏一個具體的類型來選擇一個實例,但是Heterotype構造器需要一個具體的實例來包含。 只是信息不存在。 這些部分是不兼容的。

您有點過度指定了:),以下工作正常:

data Heterotype f = forall a. f a => Heterotype a

hset :: forall f a. f a => a -> Heterotype f
hset x = Heterotype x

不同之處在於您已經量化了您的參數: (forall a. fa => a)表示此函數接受一個表達式,該表達式必須同時是任何可能的類型(調用者不能選擇特定的“a”) ,這真的沒有意義。 新版本(因此是相同的只是用Heterotype自身的構造函數)說,來電者被允許挑選的類型a ,它可以是任何東西,但必須只有一個類型(一次有效)。

習慣存在主義可能需要一些練習; 最好的方法是反復試驗:)

暫無
暫無

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

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