标签: lenses

GADT的makeLenses(Haskell)

是否有相当于makeLensesGADT?如果我有一个简单的GADT:

data D a b where
  D :: (Ord a, Ord b) => !a -> !b -> D a b
Run Code Online (Sandbox Code Playgroud)

有没有办法通过传入构造函数和字段名称列表自动生成镜头?

haskell gadt lenses

7
推荐指数
1
解决办法
485
查看次数

使用ekmett的镜头更新字段的多个子字段

来玩个游戏.我们将使用两个桩,两个都由黑色/白色侧面芯片组成.

data Pile = Pile { _blacks, _whites :: Int }
makeLenses ''Pile

data Game = Game { _pileA, _pileB :: Pile }
makeLenses ''Game
Run Code Online (Sandbox Code Playgroud)

一个非常聪明的举动是将A堆中的黑色芯片和白色芯片 - 在B堆中翻转.但是如何?

cleverMove :: Game -> Game
cleverMove game = game & pileA . blacks -~ 1
                       & pileA . whites +~ 1
                       & pileB . blacks +~ 1
                       & pileB . whites -~ 1
Run Code Online (Sandbox Code Playgroud)

不是很优雅.如何在不参考每个桩两次的情况下进行此操作?

我想出的唯一的事情(我不喜欢它):

cleverMove game = game & pileA %~ (blacks -~ 1)
                                . (whites +~ 1)
                       & pileB …
Run Code Online (Sandbox Code Playgroud)

haskell lenses

6
推荐指数
1
解决办法
1296
查看次数

使用镜头插入特定位置的列表

我正在尝试对包含元素列表的嵌套数据结构进行操作.在用各种方法解决之后,我终于决定使用镜头作为最好的方法.它们完美地用于查找和修改结构的特定元素,但到目前为止,我对如何添加新元素感到困惑.

从我读过的内容来看,我无法在技术上使用Traversal,因为它违反了Traversal定律,将新元素插入到列表中,并且假设我甚至可以首先使用Traversal找出如何做到这一点(我对Haskell仍然相当弱,并且镜头包装中大多数东西的类型签名让我头晕目眩.

具体来说,我想要完成的是,在匹配特定选择器的元素列表中找到一些元素,然后在匹配元素之前或之后插入一个新元素(函数的不同参数在之前或之后)比赛).Control.Lens是否已经拥有可以完成我正在尝试做的事情,而且我对类型签名的理解太弱而无法看到它?有没有更好的方法来完成我想要做的事情?

如果我只是想在列表的开头或结尾添加一个新元素,那么这将是相当微不足道的,但是将它插入特定于中间的某个地方是困难的部分.在我编写的一些前镜头代码中,我使用折叠来完成我想要的东西,但它开始变得粗糙在结构的更深嵌套部分(EG折叠内部的折叠内部)所以我转向Control.Lens试图解开一些混乱.

haskell list lenses

6
推荐指数
2
解决办法
879
查看次数

什么是OCaml世界中的**镜头**

任何人都可以用OCaml解释*什么是镜头?

我试图谷歌它,但几乎所有这些都在Haskell的世界.

只想在OCaml的世界中为它做一些简单的演示,比如它是什么,它可以用于什么,等等.

ocaml lenses

6
推荐指数
1
解决办法
621
查看次数

如何使用镜头在地图中查找值,增加或将其设置为默认值

在处理一个名为AppStateI want 的状态时,需要跟踪实例的数量.这些实例具有不同类型的ID InstanceId.

因此,我的州看起来像这样

import           Control.Lens

data AppState = AppState
  { -- ...
  , _instanceCounter :: Map InstanceId Integer
  }

makeLenses ''AppState
Run Code Online (Sandbox Code Playgroud)

当没有计算具有给定id的实例时,跟踪计数的函数应该产生1,n + 1否则:

import Data.Map as Map
import Data.Map (Map)

countInstances :: InstanceId -> State AppState Integer
countInstances instanceId = do
    instanceCounter %= incOrSetToOne
    fromMaybe (error "This cannot logically happen.")
              <$> use (instanceCounter . at instanceId)
  where
    incOrSetToOne :: Map InstanceId Integer -> Map InstanceId Integer
    incOrSetToOne m = case Map.lookup instanceId …
Run Code Online (Sandbox Code Playgroud)

haskell state-monad lenses

6
推荐指数
2
解决办法
547
查看次数

解释Edward Kmett镜头包中使用的词汇的资源

我正在尝试阅读Edward KmettLens包中的文档 .我不熟悉很多使用的术语(profunctor,isomorphism,monomorphic,contravariant,bifunctor等...)

在这个库中使用这些词汇时,学习一些词汇的好资源是什么.

haskell vocabulary category-theory lenses haskell-lens

6
推荐指数
1
解决办法
242
查看次数

如何组成返回Maybe(Haskell)的镜头

假设我的镜头at _需要一些Maybe a:

import Data.Map as M
m = M.fromList [(1,(2,3))]
--set 2nd element
m ^. at 1 .~ Just (4,5) 
--gives fromList [(1,(4,5))]
m ^. at 1 .~ Nothing
--gives fromList ()
Run Code Online (Sandbox Code Playgroud)

现在假设我想用另一个镜头来构图.这个镜头返回的事实Maybe a阻止我直接这样做.

m ^. at 1 . _2 .~ Just 4
--error
-- I want to get M.fromList [(1,(2,4))]
Run Code Online (Sandbox Code Playgroud)

这样做的正确方法是什么?

haskell lenses haskell-lens

6
推荐指数
1
解决办法
961
查看次数

倒车镜头的名称是什么?

镜头是一个执行不可变记录修改的函数:它复制记录修改其内容的一部分.镜头是一个库,允许您组合镜头,以获得更复杂的修改.

我正在寻找定义反向抽象的正确术语.一些比较两个对象并返回它们之间差异的函数.这些功能也产生了一个系统.每个修改可以与细粒度描述"记录内的字段C内的字段B内的字段A"或者记录内的粗"字段C"同时表示.因此,您可以使用所需的准确度进行匹配修改.

我需要编写代码来比较记录并对其中的修改做出反应.我想避免重新发明轮子.我试图谷歌反向镜头,但淹没在不相关的输出.

language-agnostic lenses haskell-lens

6
推荐指数
1
解决办法
114
查看次数

如何非毫不含糊地回复"也许"一个镜头?

类似的类型Maybe (Lens' a b)不起作用,因为Lens'在引擎盖下是Rank-2类型,不能在没有-XImpredicativeTypes扩展名的类型构造函数中包装(在GHC中实际上不支持).

因此,提供一个在道德上具有类型的函数的最佳类型是什么

foo :: A -> Maybe (Lens' B C)
Run Code Online (Sandbox Code Playgroud)

一种可能性是推迟Maybe到通过的延续

foo' :: ? y . A -> (Lens' B C -> y) -> Maybe y
Run Code Online (Sandbox Code Playgroud)

但我并不特别喜欢.

haskell higher-rank-types lenses impredicativetypes

6
推荐指数
1
解决办法
86
查看次数

有没有直接的方法将多个记录字段的setter组合到一个setter?

import Control.Lens
import Control.Lens.TH

data Foo = Foo {
    _bar, _baz :: Int
   }
makeLenses ''Foo
Run Code Online (Sandbox Code Playgroud)

现在,如果我想修改两个int字段,我可以做

barbaz :: Setter' Foo Int
barbaz = sets $ \foo f -> foo & bar %~ f
                              & baz %~ f
Run Code Online (Sandbox Code Playgroud)

但这似乎是一种非常难看的手动方式.

使用镜头/箭头组合器可以直接实现吗?

haskell arrows lenses haskell-lens

6
推荐指数
1
解决办法
277
查看次数