如何使用镜头库编写依赖于其他镜头的复杂镜头?

2024-01-03

此刻,我有一个WorkLog类型,并带有开始日期和结束日期。我还想添加一个持续时间镜头,它将从开始日期和结束日期派生出来。它应该是只读的,或者如果其值发生更改则更改结束日期(我想知道如何实现这两个版本,即使我只会使用一个版本)。

这是我的代码。基本上,如果你能实现workLogDurationRO and workLogDurationRW函数来获得主要传递中的所有测试,这将回答我的问题。

{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Lens

-- Keep times simple for this example
newtype TimeStamp = TimeStamp Int deriving (Show, Eq)
newtype TimeDifference = TimeDifference Int deriving (Show, Eq)

(-.-) :: TimeStamp -> TimeStamp -> TimeDifference
(TimeStamp a) -.- (TimeStamp b) = TimeDifference (a - b)

data WorkLog = WorkLog {
  _workLogDescription :: String
  , _workLogStartTime :: TimeStamp
  , _workLogEndTime :: TimeStamp
  }

makeLenses ''WorkLog

-- | Just return the difference between the start and end time
workLogDurationRO :: Getter WorkLog TimeDifference
workLogDurationRO = error "TODO write me!"

-- | Like the read only version, but when used with a setter,
-- change the end date.
workLogDurationRW :: Lens' WorkLog TimeDifference
workLogDurationRW = error "TODO write me!"

ensure :: String -> Bool -> IO ()
ensure _ True = putStrLn "Test Passed"
ensure msg False = putStrLn $ "Test Failed: " ++ msg

main :: IO ()
main = do
  let testWorkLog = WorkLog "Work 1" (TimeStamp 40) (TimeStamp 100)
  ensure "read only lens gets correct duration" $ 
     testWorkLog^.workLogDurationRO == TimeDifference 60
  ensure "read+write lens gets correct duration" $ 
     testWorkLog^.workLogDurationRW == TimeDifference 60
  let newWorkLog = testWorkLog & workLogDurationRW .~ TimeDifference 5
  ensure "writeable lens changes end time" $ 
     newWorkLog^.workLogEndTime == TimeStamp 45

你可以写下Getter using to(你可以给-.-降低优先级以去掉括号):

workLogDurationRO = to $ \wl -> (wl^.workLogEndTime) -.- (wl^.workLogStartTime)

但作为镜头维基 https://github.com/ekmett/lens/wiki/FAQ#wiki-using-getters说,你可能最好使用一个计算时间差的普通函数,然后你可以使用它to当您需要它作为镜头时。

您可以构建Lens'来自 getter(与上面相同)和 setter:

workLogDurationRW = lens get set
  where
    get :: WorkLog -> TimeDifference
    get wl = (wl^.workLogEndTime) -.- (wl^.workLogStartTime)

    set :: WorkLog -> TimeDifference -> WorkLog
    set wl timeDiff = wl & workLogEndTime .~ (wl^.workLogStartTime) +.+ timeDiff
      where
        TimeStamp a +.+ TimeDifference b = TimeStamp (a + b)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用镜头库编写依赖于其他镜头的复杂镜头? 的相关文章

随机推荐

  • 如何使用字符串变量作为表名进行 sqlalchemy 查询?

    如果我不清楚 我提前道歉 英语不是我的母语 如果我犯了太多错误 请随时告诉我 我是使用flask sqlalchemy的新手 在互联网上花费数小时寻找答案后感到沮丧 我想要做的是这样的查询 ModelName query filter by
  • 图像被分配给ListView的另一个行项目

    我知道 async wait 在设置适配器之前为 ListView GridView 准备数据非常方便 例如 in Activity cs async void OnCreate Bundle SavedInstanceState SetC
  • Haskell 中的 Scanl

    scanl exp y gt scanl x gt if isLetter x then update exp Literal x else if x then update exp Epsilon else if x then updat
  • jQuery UI + Gmaps = 问题(至少对我来说)帮助!

    我一发现 jQuery 就开始使用它 它非常强大 但是当我尝试将 Gmaps api 加载到 jQuery UI 带来的选项卡中时 我开始陷入困境 奇怪的是 在 IE 6 7 8 中它工作正常 但在 Firefox Safari 我使用的是
  • iFrame 上的 Angular、onLoad 函数

    我有这个 iframe 使用基本的 JavaScript 哪个触发该方法uploadDone 当 iframe 的内容被加载时 我如何在 Angular 中做同样的事情 我想在 iframe 加载时调用控制器上的函数 但我还没有看到ng o
  • Laravel 在我的路线中使用 View Composer 并出现 htmlspecial 错误

    我试图在我的路线中进行查询 以便视图编辑器加载所有记录并对其进行计数并将其显示在我的侧边栏中 我认为查询没有问题 因为它在我的 shell 中使用 php artisantinker 来测试查询的目的 但是当我尝试在我的路线中执行此操作并将
  • ModuleNotFoundError:没有名为“gin”的模块

    当我尝试做的时候 导入杜松子酒 tf 我收到此错误 ModuleNotFoundError 没有名为 gin 的模块 我应该怎么做才能解决这个问题 我最近更新了tensorflow 所以我不认为版本有问题 我找到了解决方案here http
  • Locust:如何在 n 个用户上运行任务 n 次然后停止 locust 运行?

    我有一个简单的 Locust 脚本 其中包含一个带有 http 请求的任务 我想对 10 个用户运行此任务 100 次 然后停止运行脚本 有没有什么简单的方法可以做到 我知道 run time 参数 但它只会在指定的时间后停止 下面是我的脚
  • 在同一组件内重复 html

    我正在寻找一种在组件中的多个位置重复相同标记的方法 我知道我可以使用一个新组件 但我正在寻找一些不那么严重的东西 The html
  • 更改图像的 src 属性是否会阻止图像下载?

    假设我有两个手风琴选项卡 第一个加载数百张图像 并在页面加载时打开 如果用户单击第二个手风琴选项卡 我希望能够停止下载图像 通过js改变图片的src属性会阻止图片下载吗 或者请求是否只是继续直到完成而不显示在页面上 我有一个脚本 可以在 3
  • Angular 9 PWA 社交登录重定向 start_url / 索引页面上的问题

    我的角度应用程序正在 Angular 9 上运行 带有 SSR 和 PWA 它在 Heroku cloudflare 上运行 当我尝试在索引页面上通过 Facebook Google 登录时 角度给出请求超时错误 Example 打开索引页
  • ES 6 在定义后动态地处理类

    我之前正在开发自己的 Javascript OOP 但现在我正在玩ES6并想使用该类defined after 定义以一般的方式 Note任何答案new这不是我所追求的 伪代码 base js class Base constructor
  • d3.js中的网络多路由正交图

    We want to use d3 to draw a network route graph that has fixed start and end node but different paths in between that mi
  • 具有 tmux 集成的 Iterm2 不使用 .tmux.conf 中的键绑定

    我已经在 iTerm2 中使用 tmux 一段时间了 但我还没有使用 iTerm2 现在附带的 tmux 集成 我开始考虑使用 tmux 集成 因为它允许您在 tmux 内使用 shell 集成 我遇到的问题是在我这样做之后tmux CC我
  • GWT 中的 Shift 键?

    Is there a way in GWT to tell if the Shift key is down inside of an onClick handler 例如 import com google gwt event dom c
  • 仅对少数路径禁用过滤器

    如何获取过滤器以应用于根路径之外的每个请求 我想忽略的请求除外 这是我的例子 我有一个 Spring Security 过滤器 如下所示 private static class SecurityConfiguration extends
  • Android Firebase 无法刷新电子邮件验证状态

    在我的 Android 应用程序中 我正在创建用户并发送验证电子邮件 当用户通过单击收到的电子邮件中的链接进行验证后 我想继续进入下一页 但是 验证状态未更新 因此我无法继续 我已尝试注销并再次登录 这有效 但我不想以这种方式刷新状态 有任
  • 阿帕奇扭矩项目的入口点

    我有一个项目包含webroot文件夹名称为 war 并包含类似的结构 但它不包含web xml与其他常见的 Web 项目入口点一样 我如何开始这个 Torque 项目 Torques Web 项目的入口点是什么 我的另一个问题在这里xdoc
  • Spring数据查询其中列为空的情况

    假设我有实体 为了简洁起见 省略了 getter setter 和各种细节 Entity class Customer OneToMany cascade CascadeType ALL mappedBy customer Collecti
  • 如何使用镜头库编写依赖于其他镜头的复杂镜头?

    此刻 我有一个WorkLog类型 并带有开始日期和结束日期 我还想添加一个持续时间镜头 它将从开始日期和结束日期派生出来 它应该是只读的 或者如果其值发生更改则更改结束日期 我想知道如何实现这两个版本 即使我只会使用一个版本 这是我的代码