我有使用(lens和GHC.Records的此代码(很奇怪):]
{-# LANGUAGE DataKinds, PolyKinds, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
import Control.Lens
import GHC.Records
data Glass r = Glass -- just a dumb proxy
class Glassy r where
the :: Glass r
instance Glassy x where
the = Glass
instance (HasField k r v, x ~ r)
-- instance (HasField k r v, Glass x ~ Glass r)
=> HasField k (Glass x) (ReifiedGetter r v) where
getField _ = Getter (to (getField @k))
data Person = Person { name :: String, age :: Int }
main :: IO ()
main = do
putStrLn $ Person "foo" 0 ^. runGetter (getField @"name" the)
[这个想法是有一个HasField
实例,它会从代理中变出HasField
,只是为了它的地狱。但它不起作用:
ReifiedGetter
我不明白为什么ReifiedGetter
仍然模棱两可。我使用了* Ambiguous type variable `r0' arising from a use of `getField'
prevents the constraint `(HasField
"name"
(Glass r0)
(ReifiedGetter Person [Char]))' from being solved.
,我的直觉是实例头应该匹配,然后类型检查器将在前提条件中找到r0
,这将消除歧义。
如果将constraint trick更改为r0 ~ Person
,则可以消除歧义,并且可以正常编译。但是为什么它起作用,为什么它不起作用?
也许令人惊讶的是,它与(HasField k r v, x ~ r)
的种类有关: