簡體   English   中英

Haskell 類型變量無法解析

[英]Haskell type variable not resolving

我有以下代碼片段

class LatticeElement a where
    next :: a -> a -- next element     

class (Ord a, LatticeElement a) => LatticeDate a where
    prev :: a -> a -- prev date

data LatticeSlice d v = forall d v. (LatticeDate d, LatticeElement v) => LatticeSlice{date :: d, slice :: v}

map :: (v -> w) -> LatticeSlice d v -> LatticeSlice d w
map f LatticeSlice{date = d, slice = sl} = LatticeSlice{date = d, slice = f sl}

這會導致編譯錯誤。 現在,據我了解代碼,首先我將LatticeElement設置為類型類,然后將LatticeDate設置為LatticeElement類型清除的特化,要求類型dOrd的實例。

現在我創建LatticeSlice ,並聲明我讀到類似“ LatticeSlice是類型dv的數據類型,僅限於所有類型d實例化LatticeDatev實例化LatticeElement

錯誤出現在map的實例化中:

src/Lattice.hs:9:77: error:
    • Couldn't match expected type ‘v’ with actual type ‘v1’
      ‘v1’ is a rigid type variable bound by
        a pattern with constructor:
          LatticeSlice :: forall d1 v1 d2 v2.
                          (LatticeDate d2, LatticeElement v2) =>
                          d2 -> v2 -> LatticeSlice d1 v1,
        in an equation for ‘map’
        at src/Lattice.hs:9:7-40
      ‘v’ is a rigid type variable bound by
        the type signature for:
          Lattice.map :: forall v w d.
                         (v -> w) -> LatticeSlice d v -> LatticeSlice d w
        at src/Lattice.hs:8:1-55
    • In the first argument of ‘f’, namely ‘sl’
      In the ‘slice’ field of a record
      In the expression: LatticeSlice {date = d, slice = f sl}
    • Relevant bindings include
        sl :: v1 (bound at src/Lattice.hs:9:38)
        f :: v -> w (bound at src/Lattice.hs:9:5)
        map :: (v -> w) -> LatticeSlice d v -> LatticeSlice d w
          (bound at src/Lattice.hs:9:1)

我認為編譯器告訴我它沒有將(v -> w)中的v解析為與LatticeSlice dv中的v相同的類型。 但是我不知道它為什么要這樣做,或者更重要的是,該怎么辦!

首先, forall d v.掩蓋了LatticeSlice的論點。

                  d1           d2                d2                                           d2
                  |            |                 |                                            |
                  v            v                 v                                            v
data LatticeSlice d v = forall d v. (LatticeDate d, LatticeElement v) => LatticeSlice{date :: d, slice :: v}
                    ^            ^                                 ^                                      ^
                    |            |                                 |                                      |
                    v1           v2                                v2                                     v2

LatticeSlice的類型證明了這一點

>> :set -fprint-explicit-foralls
>> :t +v LatticeSlice
LatticeSlice
  :: forall d1 v1 d2 v2.
     (LatticeDate d2, LatticeElement v2) =>
     d2 -> v2 -> LatticeSlice d1 v1

值構造函數的參數類型有d2v2與類型構造函數d1v1的參數無關:

instance LatticeDate    ()
instance LatticeElement ()

ls :: LatticeSlice d v
ls = LatticeSlice () ()

如果你刪除了你的數據類型攜帶約束的forall量詞,在這種情況下,我建議再次使用它! 它相當於這個 GADT:

data LatticeSlice d v where
  LatticeSlice :: (LatticeDate d, LatticeElement v) => {date :: d, slice :: v} -> LatticeSlice d v

約束阻礙了您的定義, mapw參數中不能是參數化的。 僅僅因為vLatticeElement並不意味着w是。 因此我們必須證明f sl :: w是一個LatticeElement w

map :: LatticeElement w => (v -> w) -> LatticeSlice d v -> LatticeSlice d w
map f LatticeSlice{date = d, slice = sl} = LatticeSlice{date = d, slice = f sl}

這使得它與Functor ( Applicative , Monad ..) 和Bifunctor ( Biapplicative , ..) 等基礎設施不兼容。

這是最好的版本,如果您需要晶格約束,您可以將它們添加到在LatticeSlice上運行的函數中

data LatticeSlice d v = LatticeSlice {date :: d, slice :: v}
  deriving stock Functor

instance Bifunctor LatticeSlice where
  bimap :: (d -> d') -> (s -> s') -> (LatticeSlice d s -> LatticeSlice d' s')
  bimap f g as = bipure f g <<*>> as

instance Biapplicative LatticeSlice where
  bipure :: d -> s -> LatticeSlice d s
  bipure = LatticeSlice

  biliftA2 :: (d1 -> d2 -> d3)
           -> (s1 -> s2 -> s3)
           -> (LatticeSlice d1 s1 -> LatticeSlice d2 s2 -> LatticeSlice d3 s3)
  biliftA2 (·) (×) (LatticeSlice d1 s1) (LatticeSlice d2 s2) =
    LatticeSlice (d1 · d2) (s1 × s2)

觀看 Edward Kmett 的Type Classes vs. the World了解更多信息。

暫無
暫無

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

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