为什么“约束技巧”在此手动定义的HasField实例中不起作用?

问题描述 投票:5回答:1

我有使用(lensGHC.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,则可以消除歧义,并且可以正常编译。但是为什么它起作用,为什么它不起作用?

haskell typeclass typechecking
1个回答
5
投票

也许令人惊讶的是,它与(HasField k r v, x ~ r)的种类有关:

© www.soinside.com 2019 - 2024. All rights reserved.