使用DuplicateRecordFields消除记录更新的歧义

时间:2017-12-17 10:02:59

标签: haskell records ambiguous-call

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

这是一个简化的例子:

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

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

有没有办法让这项工作?

3 个答案:

答案 0 :(得分: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 }

答案 1 :(得分:1)

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

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

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

我不是DuplicateRecordFields的粉丝。为什么不去the lens route

{-# 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

答案 2 :(得分:0)

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

-}

参考文献: