Tôi có mã này (phải thừa nhận là lạ) sử dụng ống kính và 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)
Ý tưởng là có một HasField
ví dụ gợi ReifiedGetter
ra từ một proxy, chỉ vì địa ngục của nó. Nhưng nó không hoạt động:
* Ambiguous type variable `r0' arising from a use of `getField'
prevents the constraint `(HasField
"name"
(Glass r0)
(ReifiedGetter Person [Char]))' from being solved.
Tôi không hiểu tại sao r0
vẫn còn mơ hồ. Tôi đã sử dụng thủ thuật ràng buộc và trực giác của tôi là phần đầu cá thể phải khớp, sau đó bộ đánh máy sẽ tìm thấy r0 ~ Person
trong các điều kiện tiên quyết và điều đó sẽ loại bỏ sự mơ hồ.
Nếu tôi thay đổi (HasField k r v, x ~ r)
thành (HasField k r v, Glass x ~ Glass r)
điều đó sẽ loại bỏ sự mơ hồ và nó sẽ biên dịch tốt. Nhưng tại sao nó hoạt động, và tại sao nó không hoạt động theo cách khác?