标签: lenses

使用Monocle Lenses使用另一个属性的值修改属性

我有以下型号

import monocle.macros.Lenses
import monocle.function.all._
import monocle.std.list._

@Lenses("_") case class Poll(pollChoices: List[PollChoice], totalVoteCount: Int)
@Lenses("_") case class PollChoice(id: Int, value: Int, percentage: Int)
Run Code Online (Sandbox Code Playgroud)

我想要实现的是通过更新pollChoices列表中每个元素的所有百分比属性来更新Poll的pollChoices属性.我的问题是,新的百分比值是基于价值的属性PollChoicetotalValueCount中的投票.

到目前为止我所做的是:

val poll = Poll(List(PollChoice(1,3,0), PollChoice(2,5,0)), 8)

(Poll._pollChoices composeTraversal each composeLens PollChoice._percentage)
  .modify(oldPercentage => oldPercentage + 1)(poll)
Run Code Online (Sandbox Code Playgroud)

但是这样我只能访问我在修改步骤中更新的元素的百分比属性,我也需要该值.

我假设我需要使用Traversable来进行这种修改,但我不确定如何.谢谢.

scala lenses monocle

8
推荐指数
1
解决办法
105
查看次数

部分镜片的组成

我试图找出最简洁的方法来修改嵌套在Maybe类型(或其他类型的建模偏好)内的值.

以下是示例设置:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data Outer = Outer { _inner :: Maybe Inner }
  deriving (Show)

data Inner = Inner { _foo :: Int }
  deriving (Show)

makeLenses ''Outer
makeLenses ''Inner
Run Code Online (Sandbox Code Playgroud)

通过以下方式以一种混乱的方式执行此操作非常容易lens:

wibble :: Outer -> Maybe Outer
wibble o = do i <- view inner o
              let i' = over foo succ i
              return $ set inner (Just i') o
Run Code Online (Sandbox Code Playgroud)

为了说明为什么这是令人讨厌的,这是我想要写的:

wibble' :: Outer -> Maybe Outer
wibble' = overish inner.foo …
Run Code Online (Sandbox Code Playgroud)

haskell lenses

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

Control.Lens性能开销

我很欣赏Control.Lens包.它确实有助于稍微弱的Haskell记录语法.我正在研究图书馆的某些部分,其中表现是一个问题.有没有人知道如果有的话,使用通过类型类暴露的简单镜头(如下所示)与功能中的基本模式匹配相比会有什么性能损失?使用像这样的镜头有可能成为记录命名空间冲突问题的一个很好的工作.我可以自己设置一些基准测试,但是如果有人可以帮我解决问题,我很好奇.谢谢.

镜头课程

class LensX v where
  _x :: Functor f => (Double -> f Double) -> v -> f v

class LensY v where
  _y :: Functor f => (Double -> f Double) -> v -> f v

class LensZ v where
  _z :: Functor f => (Double -> f Double) -> v -> f v 
Run Code Online (Sandbox Code Playgroud)

镜头实例

instance LensX Vec3 where
  _x f (Vec3 x y z) = fmap (\x' -> Vec3 x' y z) (f x)

instance LensY Vec3 …
Run Code Online (Sandbox Code Playgroud)

performance haskell lenses

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

用镜头构造谓词

我想A -> Bool用A的一些镜头创建一个函数.例如:

data A = A { _foo :: Int, _bar :: Int }
makeLenses ''A

l :: [A]

l' = filter (\a -> a^.foo > 100) l
Run Code Online (Sandbox Code Playgroud)

过滤谓词看起来有点块状.((>100).(^.foo))并没有好多少.没有镜头,我会用((>100) . foo).

有没有一种很好的方法来创建这样的谓词lens?理想情况下,它也允许谓词(\a -> a^.foo > 100 && a^.bar < 50).

haskell lenses

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

在Haskell中使用Lens来修改值

我经常发现自己使用这种模式:

do
    let oldHeaders = mail ^. headers
    put $ (headers .~ (insert header value oldHeaders)) mail
Run Code Online (Sandbox Code Playgroud)

这看起来像Control.Lens应该能做的事情,但我想我还没有找到合适的操作员.有没有更好的办法?另外,在这段代码中我还应该做些什么吗?

haskell lenses haskell-lens

7
推荐指数
2
解决办法
951
查看次数

使用镜头两次

我正在努力使用该lens库来解决特定问题.我想通过

  1. 更新的数据结构
  2. 镜头专注于更新结构的一部分

到另一个功能,g.我传递了镜头和数据结构,因为g需要来自数据结构的一些共享信息以及一条信息.(如果它有帮助,数据结构包含关于联合概率分布的信息,但g只能在边缘上工作,需要知道我正在看哪个边缘.两个边缘之间的唯一区别是它们与其定义的其余部分的平均值在数据结构中共享).

我的第一次尝试看起来像这样

f :: Functor f => Params -> ((Double -> f Double) -> Params -> f Params) -> a
f p l = g (l %~ upd $ p) l
  where upd = ...

g p x = go p p^.x
Run Code Online (Sandbox Code Playgroud)

但是在编译过程中失败了,因为它f被推断为Identity更新和Const Doublegetter.

完成我想做的最好的方法是什么?我可以想象能够做到以下之一:

  1. 制作镜头的副本,以便在每种情况下类型推断可以不同
  2. 我没有通过更新的结构和镜头,而是通过原始结构和一个返回修改值的镜头(如果我只想更新镜头所看到的结构部分).
  3. 为我的功能/数据结构做出更好的设计选择
  4. 完全不同的东西

谢谢你的帮助!

haskell lenses haskell-lens

7
推荐指数
2
解决办法
293
查看次数

仅从模块导出getter或setter

有没有办法让我只从具有镜头的模块中导出特定的吸气剂xor setter?

例如,让我们假设一个数据结构具有一直存在的不变性,>= 0仅通过递增它并仅使用初始值创建来修改0:

module Something
    ( Counter
    -- export only `count` getter
    , make
    , increment
    ) where

data Counter = Counter { _count :: Int } deriving (Eq)
makeLenses ''Positive

make :: Counter
make = Counter 0

increment :: Counter -> Counter
increment c = c ^. count %~ (+1)
Run Code Online (Sandbox Code Playgroud)

我怎么能只导出count吸气剂?

haskell invariants lenses haskell-lens

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

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
查看次数

是否可以仅使用常量属性在两个结构之间实现双向关系?

我的用例基于以下模型:

struct Person {
  let name: String
  let houses: [House]
}

struct House {
  let owner: Person
}
Run Code Online (Sandbox Code Playgroud)

现在,理想情况下,我希望保持双向关系,要求每个房子只有一个所有者,其中所有者也应该知道其所有房屋.

使用上述数据结构,是否可以创建实例,House并且Person两者之间存在关系,并且对象基本上是相互指向的?

我猜这个的措辞已经有点误导了,因为由于structs 的值语义,它们并没有真正指向任何地方,而只是持有值的副本.看起来很明显,用双向关系创建这两个对象是不可能的,但我仍然想确定并在这里提出这个问题!

一个明显的解决方案也是使用housesowner变量使用var而不是let在声明它们时,然后可以在每个的初始化器中维护关系struct:

struct Person {
  let name: String
  var houses: [House]

  init(name: String, houses: [House]) {
    self.name = name
    self.houses = houses
    self.houses = houses.map { (house: House) in
      var newHouse = house
      newHouse.owner = self
      return newHouse
    }
  }
}


struct House …
Run Code Online (Sandbox Code Playgroud)

functional-programming immutability ios lenses swift

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

缩放是否有"双重"?

zoom 允许我们在实际定义了更多变量的上下文中使用仅使用某些状态变量的状态操作.

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

import Control.Monad.Trans.State
import Control.Monad.IO.Class

data Galaxy = Galaxy {
    _solarSys :: SolarSystem
  , _otherStars :: String
  } deriving (Show)
data SolarSystem = SolarSystem {
    _sun :: Float
  , _planets :: Int
  } deriving (Show)

makeLenses ''SolarSystem
makeLenses ''Galaxy

main = (`runStateT`Galaxy (SolarSystem 2e+30 8) "") $ do
   zoom solarSys $ do
      sun -= 1e+23
      planets += 1
   liftIO . print =<< get
Run Code Online (Sandbox Code Playgroud)
Galaxy {_solarSys = SolarSystem {_sun = 1.9999999e30, _planets = 9}, …

haskell state-monad lenses haskell-lens

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