2

我正在使用 DuplicateRecordFields (+OverloadedLabels) 扩展,我遇到了一种情况,我无法弄清楚如何在记录更新中消除歧义。

这是一个简化的示例:

data A = A { name :: String }
data B = B { name :: String }

combine :: A -> B -> A
combine a b = a { name = name b }

有什么办法可以使这项工作?

4

3 回答 3

2

或者,您可以机械地使用getFieldfromGHC.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"}

-}

参考:

于 2019-05-11T06:29:09.973 回答
2

我在之前的一个问题中回答了关于-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 }
于 2017-12-18T02:12:48.863 回答
1

您可以匹配模式中的名称:

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
于 2017-12-17T12:13:07.183 回答