Haskell记录中的名称冲突 [英] Name conflicts in Haskell records

查看:77
本文介绍了Haskell记录中的名称冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Haskell对记录成员没有点符号。对于每个记录成员,编译器使用类型RecType - > FieldType创建一个具有相同名称的函数。这会导致名称冲突。有什么办法可以解决这个问题,即如何使用相同的字段名称来创建多个记录?解析方案

另一种方法避免这个问题是使用镜头包。它提供了一个makeFields模板haskell函数,你可以像这样使用它:

  { - #LANGUAGE FlexibleInstances# - } $ b $ $ {$#$} 
{ - #语言MultiParamTypeClasses# - }
{ - #LANGUAGE TemplateHaskell# - }
{ - #LANGUAGE TypeSynonymInstances# - }
Control.Lens

data A = A
{_aText :: String
}
makeFields''A - 为每个记录存取器创建一个镜头x,其名称_aX

数据B = B
{_bText :: Int
,_bValue :: Int
}
- 为每个记录访问器创建一个镜头x名称为_bX
makeFields''B

main = do
let a = Ahello
let b = B 42 1

- (^。)是访问某个值(a)的字段(文本)的镜头的函数
putStrLn $a:++ a ^的文本。文本
putStrLn $b的文本:++ show(b ^ .text)

如果您不想使用TemplateHaskell和镜头,您还可以手动使用TemplateHaskell自动执行的镜头: #LANGUAGE FlexibleInstances# - }
{ - #LANGUAGE FunctionalDependencies# - }
{ - #LANGUAGE MultiParamTypeClasses# - }
{ - #LANGUAGE TypeSynonymInstances# - }
data A = A
{aText :: String
}

data B = B
{bText :: Int
,bValue :: Int
}

- 类型为a的类,它具有t
类型的text字段HasText at | a - > t其中

- 文本值的访问者
text :: a - > t

- 使这两个类型的实例成为这些
实例HasText一个字符串其中text = aText
实例HasText B Int其中text = bText

main = do
let a = Ahello
let b = B 42 1
putStrLn $a:++ text a
putStrLn $的文本b :++ show(text b)

但我真的可以推荐学习镜头,因为它也提供很多其他工具,比如修改或设置一个字段。


Haskell doesn't have dot notation for record members. For each record member a compiler creates a function with the same name with a type RecType -> FieldType. This leads to name conflicts. Are there any ways to work around this, i.e. how can I have several records with the same field names?

解决方案

Another way to avoid this problem is to use the lens package. It provides a makeFields template haskell function, which you can use like this:

{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE TemplateHaskell        #-}
{-# LANGUAGE TypeSynonymInstances   #-}
import           Control.Lens

data A = A
  { _aText :: String
  }
makeFields ''A   -- Creates a lens x for each record accessor with the name _aX

data B = B
  { _bText  :: Int
  , _bValue :: Int
  }
-- Creates a lens x for each record accessor with the name _bX
makeFields ''B  

main = do
  let a = A "hello"
  let b = B 42 1

  -- (^.) is a function of lens which accesses a field (text) of some value (a)
  putStrLn $ "Text of a: " ++ a ^. text 
  putStrLn $ "Text of b: " ++ show (b ^. text)

If you don't want to use TemplateHaskell and lens, you can also do manually what lens automates using TemplateHaskell:

{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE TypeSynonymInstances   #-}
data A = A
  { aText :: String
  }

data B = B
  { bText  :: Int
  , bValue :: Int
  }

-- A class for types a that have a "text" field of type t
class HasText a t | a -> t where

  -- An accessor for the text value
  text :: a -> t

-- Make our two types instances of those
instance HasText A String where text = aText
instance HasText B Int where text = bText

main = do
  let a = A "hello"
  let b = B 42 1
  putStrLn $ "Text of a: " ++ text a
  putStrLn $ "Text of b: " ++ show (text b)

But I can really recommend learning lens, as it also provides lots of other utilities, like modifying or setting a field.

这篇关于Haskell记录中的名称冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆