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
インスタンスを持っている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
曖昧なままなのか分かりません。私は制約トリックを使用しましたが、私の直感は、インスタンスヘッドが一致する必要があるということです。それから、タイプチェッカーはr0 ~ Person
前提条件を見つけ、あいまいさを取り除きます。
私がそれに変更(HasField k r v, x ~ r)
する (HasField k r v, Glass x ~ Glass r)
と、あいまいさがなくなり、うまくコンパイルされます。しかし、なぜそれが機能し、なぜそれが逆に機能しないのでしょうか?