我正在使用GHC 8.2.1。我有以下模块:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Moat (Moat,moat) where

import GHC.Records (HasField(..))

newtype Moat r = Moat r

moat :: r -> Moat r
moat = Moat

instance HasField s r v => HasField s (Moat r) v where
    getField (Moat r) = getField @s r


还有另外一个:

module Foo (Foo(..)) where

data Foo a = Foo { getDims :: (Int, Int), getData :: [a] }


我的问题是,当我同时导入了两个模块并且尝试执行以下操作时:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE DataKinds #-}
import Moat
import Foo
import GHC.Records

oops :: (Int,Int)
oops = getField @"getDims" (moat (Foo (5,5) ['c']))


我收到此错误:

No instance for (HasField "getDims" (Moat (Foo Char)) (Int, Int))
       arising from a use of ‘getField’


为什么无法解析HasField实例?

最佳答案

通过在定义{-# LANGUAGE PolyKinds #-}实例的Moat模块中启用HasField可以解决该问题。

我想这与HasField类型类的种类有关:

λ :info HasField
class HasField k (x :: k) r a | x r -> a where
    getField :: r -> a


这使我们可以像这样定义HasField实例,其中字段选择器是非Symbol类型的:

import GHC.Records
data A = A B
data B = B deriving Show
instance HasField B A B where
    getField (A b) = b


在ghci中:

λ> getField @B (A B)
B

08-26 15:10