本文介绍了用于获取或设置由运行时参数确定的记录字段的镜头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这些类型(还有更多):

I have these types (and more):

data Player = PlayerOne | PlayerTwo deriving (Eq, Show, Read, Enum, Bounded)

data Point = Love | Fifteen | Thirty deriving (Eq, Show, Read, Enum, Bounded)

data PointsData =
  PointsData { pointsToPlayerOne :: Point, pointsToPlayerTwo :: Point }
  deriving (Eq, Show, Read)

我正在网球kata ,作为实现的一部分,我想使用一些使我能够获取或设置任意播放器的点的功能,这些功能仅在运行时才知道.

I'm doing the Tennis kata, and as part of the implementation, I'd like to use some functions that enable me to get or set the points for an arbitrary player, only known at runtime.

形式上,我需要像这样的功能:

Formally, I need functions like these:

pointFor :: PointsData -> Player -> Point
pointFor pd PlayerOne = pointsToPlayerOne pd
pointFor pd PlayerTwo = pointsToPlayerTwo pd

pointTo :: PointsData -> Player -> Point -> PointsData
pointTo pd PlayerOne p = pd { pointsToPlayerOne = p }
pointTo pd PlayerTwo p = pd { pointsToPlayerTwo = p }

如所示,我的问题不是我无法实现这些功能.

As demonstrated, my problem isn't that I can't implement these functions.

但是,它们对我来说确实像 lens-,所以我想知道是否可以通过lens库获得该功能?

They do, however, look lens-like to me, so I wonder if I could get that functionality via the lens library?

大多数镜头教程都展示了如何获取或设置更大数据结构中特定的命名部分.这似乎不太适合我在这里要做的事情;相反,我正在尝试获取或设置在运行时确定的子部件.

Most of the lens tutorials show how to get or set a particular, named part of a bigger data structure. This doesn't quite seem to fit what I'm trying to do here; rather, I'm trying to get or set a sub-part determined at runtime.

推荐答案

基于 Fyodor Soikin 答案> 和 duplode 的注释,最后我使用了 lens 中的makeLenses并编写了一个返回合适的透镜的函数:

Based on the answer from Fyodor Soikin and comment from duplode, I ended up using makeLenses from lens and writing a function that returns the appropriate lens:

data PointsData =
  PointsData { _pointsToPlayerOne :: Point, _pointsToPlayerTwo :: Point }
  deriving (Eq, Show, Read)
makeLenses ''PointsData

playerPoint :: Player -> Lens' PointsData Point
playerPoint PlayerOne = pointsToPlayerOne
playerPoint PlayerTwo = pointsToPlayerTwo

它可以像更大功能的这个片段一样使用:

It can be used like this fragment of a bigger function:

score :: Score -> Player -> Score
-- ..
score (Points pd) winner = Points $ pd & playerPoint winner %~ succ
-- ..

这篇关于用于获取或设置由运行时参数确定的记录字段的镜头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 20:12