簡體   English   中英

未找到通用的類型類實例

[英]Typeclass instance not found for generic

我不能讓GHC解決通用類型類的實例如下:(我們的目標是達到相同的效果訪問屬性xpointx point ,而且,由於不是利用類型級別的字符串)

data Label (l :: Symbol) =
  Get

class Has a l b | a l -> b where
  get :: a -> Label l -> b

instance (Generic r, GenericHas (Rep r) pl pt) => Has r pl pt where
  get = genericHas . from

class GenericHas a l b | a l -> b where
  genericHas :: a x -> Label l -> b

instance GenericHas (D1 a (C1 b (S1 (c ('Just pl) d e f) (Rec0 pt)))) pl pt where
  genericHas (M1 (M1 (M1 (K1 v)))) _ = v

data Point =
  Point
    { x :: Int
    }
  deriving (Show, Generic)

example :: Int
example = get (Point 1) (Get :: Label "x")

以下是錯誤:

* No instance for (GenericHas
                         (D1
                            ('MetaData
                               "Point"
                               "Alba.Persistence"
                               "alba-0.1.0.0-w6KgEimatKAP1g0rWS7YT"
                               'False)
                            (C1
                               ('MetaCons "Point" 'PrefixI 'True)
                               (S1
                                  ('MetaSel
                                     ('Just "x")
                                     'NoSourceUnpackedness
                                     'NoSourceStrictness
                                     'DecidedLazy)
                                  (Rec0 Int))))
                         "x"
                         Int)
        arising from a use of `get'
    * In the expression: get (Point 1) (Get :: Label "x")
      In an equation for `example':
          example = get (Point 1) (Get :: Label "x")

問題是GHC無法將c'MetaSel匹配,因為'MetaSel是更高級別的。 默認情況下,假設新類型變量具有種類* ,因此匹配在此處失敗。

解決這個問題的一種方法是用'MetaSel替換c

instance GenericHas (D1 a (C1 b (S1 (`MetaSel ('Just pl) d e f) (Rec0 pt)))) pl pt where

另一種方法是啟用PolyKinds 這將告訴GHC 不要對新變量采取類型* ,匹配將成功。


額外獎勵:您可以使用TypeApplications獲得更好的語法。 您可以編寫Get @"x"而不是Get :: Label "x" 或者你可以更進一步,定義一個包裝Get的函數:

get' :: forall (l :: Symbol) a b. Has a l b => a -> b
get' a = get a (Get @l)

-- Usage:
example = get' @"x" (Point 1)

暫無
暫無

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

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