如何用镜头处理重复的记录字段?

问题描述 投票:0回答:1

给出这段代码:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FunctionalDependencies #-}

module Foo where

import Control.Lens ((^.), makeFieldsNoPrefix)
import Prelude hiding (id)

data Bar
  = Bar1 { _id :: Int
         , _name :: String
         }
  | Bar2 { _name :: String }

$(makeFieldsNoPrefix ''Bar)


data Foo = Foo { _id :: Int
               , _name :: String
               }

$(makeFieldsNoPrefix ''Foo)

a = (undefined :: Foo) ^. name -- compiles fine

b = (undefined :: Foo) ^. id -- doesnt compile
{-
    • No instance for (Monoid Int) arising from a use of ‘id’
    • In the second argument of ‘(^.)’, namely ‘id’
      In the expression: (undefined :: Foo) ^. id
      In an equation for ‘b’: b = (undefined :: Foo) ^. id
-}

据我所知,似乎id需要一个Monoid实例,因为Bar在实例为Bar2类型(它没有id字段时可能会失败)。

但是由于我正在使用Foo(始终具有id字段),所以它应该可以工作,不是吗?

我知道我可以通过在字段前面加上类名来解决此问题:

data Foo = Foo { _fooId :: Int, _fooName :: String }

但是如果有一个不错的解决方案而又不会弄乱我的字段名称,那么我全力以赴:-)

haskell lens monoids
1个回答
0
投票

因此,这里的问题部分是由sum-type中使用的记录引起的。我们可以为Foo的name生成一个镜头,因为每个构造函数都有一个name字段;但是只有一个构造函数具有id。这将导致TemplateHaskell生成以下HasId类,您可以通过在ghci中运行:browse Foo来自己查看:

© www.soinside.com 2019 - 2024. All rights reserved.