我正在使用 DuplicateRecordFields (+OverloadedLabels) 扩展,我遇到了一种情况,我无法弄清楚如何在记录更新中消除歧义。
这是一个简化的示例:
data A = A { name :: String }
data B = B { name :: String }
combine :: A -> B -> A
combine a b = a { name = name b }
有什么办法可以使这项工作?
我正在使用 DuplicateRecordFields (+OverloadedLabels) 扩展,我遇到了一种情况,我无法弄清楚如何在记录更新中消除歧义。
这是一个简化的示例:
data A = A { name :: String }
data B = B { name :: String }
combine :: A -> B -> A
combine a b = a { name = name b }
有什么办法可以使这项工作?
或者,您可以机械地使用getField
fromGHC.Records
来消除歧义,如下所示:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE TypeApplications #-}
module DRF where
import GHC.Records (getField)
data A = A { name :: String } deriving Show
data B = B { name :: String }
combine :: A -> B -> A
combine a b = a { name = getField @"name" b }
{- in ghci
Prelude DRF> a = A "Alice"
Prelude DRF> b = B "Bob"
Prelude DRF> DRF.combine a b
A {name = "Bob"}
-}
参考:
我在之前的一个问题中回答了关于-XDuplicateRecordFields
当前 GHC 不会从其参数中推断记录字段类型的问题:
您现在可以做的是name
明确指定提取器的类型,如下所示:
{-# LANGUAGE DuplicateRecordFields #-}
data A = A { name :: String }
data B = B { name :: String }
combine :: A -> B -> A
combine a b = a { name = (name :: B -> String) b }
您可以匹配模式中的名称:
data A = A { name :: String }
data B = B { name :: String }
combine :: A -> B -> A
combine a B{name = nb} = a { name = nb }
虽然我不喜欢DuplicateRecordFields
。为什么不走镜头路线呢?
{-# LANGUAGE TemplateHaskell, FlexibleInstances, FunctionalDependencies #-}
import Control.Lens
import Control.Lens.TH
data A = A { _aName :: String }
makeFields ''A
data B = B { _bName :: String }
makeFields ''B
combine :: A -> B -> A
combine a b = a & name .~ b^.name