我有一个深度嵌套的数据结构,我正在使用Control.Lens.*来简化在状态monad中访问它的值.
请考虑以下事项:
data Config = Config { _foo :: Maybe Int
, _bar :: Int
}
$(makeLenses ''Config)
Run Code Online (Sandbox Code Playgroud)
如何在"可爱"上"操作"地操作?我想写一个惯用的吸气剂:
config = Config (Just 1) 0
config^.foo.to fmap (+1) == Just 2
Run Code Online (Sandbox Code Playgroud)
更好的是,当Config嵌套得更深时,我们将如何处理这种情况?
data Config = { _foo :: Maybe Foo }
data Foo = Foo { _bar :: Bar }
data Bar = Bar Int
$(makeLenses ''Bar)
$(makeLenses ''Foo)
Run Code Online (Sandbox Code Playgroud)
我们可以使用访问器foo和bar来返回修改后的Bar吗?
如何使用镜头语法检查地图是否有键?
import qualified Map as Map
let x = Map.member "bla" m
Run Code Online (Sandbox Code Playgroud)
如何使用镜头来写这个?
我试图找出一种方法,如何以允许以下方式结合traverseOf使用>>=。
TLDR;一个简单的 Haskell 示例就是这样,但是在数据结构的深处使用镜头。
?> fmap concat $ mapM ((return :: a -> IO a) . const ["he", "he"]) ["foo", "bar", "baz"]
["he","he","he","he","he","he"]
Run Code Online (Sandbox Code Playgroud)
这是一个带有示例的冗长解释
data Foo = Foo [Bar] deriving Show
data Bar = Baz | Qux Int [String] deriving Show
makePrisms ''Foo
makePrisms ''Bar
items :: [Foo]
items = [Foo [Baz], Foo [Qux 1 ["hello", "world"], Baz]]
-- Simple replacement with a constant value
constReplace :: [Foo]
constReplace = over (traverse._Foo.traverse._Qux._2.traverse) (const "hehe") items
-- …Run Code Online (Sandbox Code Playgroud) 想知道如何最好地将Control.Lens包与IORefs 结合起来.具体来说,我希望能够使用atomicModifyIORef镜头,以便我可以提供类型的功能,a -> (a, b)并从操作返回一个值.代码段:
let inc x = (x+1, x)
ior <- newIORef ((1, 1) :: (Int, Int))
thisShouldBe1 <- ior & atomicModifyIORef ?? _1 inc -- this is the bit I'm stuck on
Run Code Online (Sandbox Code Playgroud) 我想编写一个函数,在Lens stab的帮助下将函数(a - > b)转换为函数(s - > t)(编辑:我意识到这个函数已经存在Setter s t a b并且被称为over或者%~,但是它没有回答下面使用镜头获取值的问题).看起来很简单,但我遇到了一个令人困惑的类型错误.要创建一个更小的示例,请考虑以下函数,它只返回镜头从第二个参数中提取的值:
f :: Lens s t a b -> s -> a
f l s = s ^. l
Run Code Online (Sandbox Code Playgroud)
这不编译.在^的第二个参数中有2个错误.(即l):
但是,以下编译:
f :: Getter s a -> s -> a
f l s = s ^. l
Run Code Online (Sandbox Code Playgroud)
然后,我意识到在镜头类型的层次结构中,Lens和Getter之间的箭头指定s = t,a = b.有没有办法使用常规从Lens s t a b类型a的值中获取类型的值s?
我有一个镜头指向一个 json 文档,例如
doc ^? ((key "body").values)
Run Code Online (Sandbox Code Playgroud)
现在我想用键“key”对 body 中的值进行索引,因为 json 看起来像
{"body": [{"key": 23, "data": [{"foo": 1}, {"foo": 2}]}]}
Run Code Online (Sandbox Code Playgroud)
所以我正在寻找一些可以让我通过另一个镜头进行索引的东西:
doc ^? key "body" . values
. indexWith (key "key")
. key "data" . values
. key "foo" . withIndex
Run Code Online (Sandbox Code Playgroud)
应该返回
[(23, 1), (23, 2)]
Run Code Online (Sandbox Code Playgroud)
MVCE:
#!/usr/bin/env stack
-- stack --resolver lts-11.7 script
-- --package lens
-- --package text
-- --package lens-aeson
{-# LANGUAGE OverloadedStrings #-}
import Control.Lens
import Data.Aeson.Lens
import Data.Text
doc :: Text
doc = …Run Code Online (Sandbox Code Playgroud) 我有这些镜头:
getB :: Lens' A (Maybe B)
getC :: Prism' B C
Run Code Online (Sandbox Code Playgroud)
如何Maybe C从A中提取a ?我能找到的最好的:
case A ^. getB of
Just b -> b ^? getC
Nothing -> Nothing
Run Code Online (Sandbox Code Playgroud)
还有更优雅的吗?
第一次使用lens。set并over变得足够简单,我认为这会很简单view:使用相同的方案来引用内部部分,但不提供新的值或函数。但是不。tst3 below gives the error below the code。有人知道发生了什么事吗?
-- Testing lenses
tst1 = set (inner . ix 0 . w) 9 outer
tst2 = over (inner . ix 0 . w) (+2) outer
tst3 = view (inner . ix 0 . w) outer -- this line errors out
* No instance for (Monoid Int) arising from a use of `ix'
* In the first argument of `(.)', namely `ix 0' …Run Code Online (Sandbox Code Playgroud) 我正在使用 GHC 9.2.2 并使用OverloadedRecordDotgeneric -lens。作为一个实验,我想使用重载点作为通用镜头功能(包括类型更改更新)的“前端”。
我有这些辅助定义:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverloadedRecordDot #-}
import Control.Lens ( (&), (.~), Lens )
import Data.Generics.Product.Fields qualified as G
import GHC.Records (HasField (..))
import GHC.TypeLits (Symbol)
import GHC.Generics (Generic)
-- Basically a 'Control.Lens.Reified.ReifiedLens'.
newtype Lensy s t a b = Lensy (Lens s t a b)
pry :: Lensy s t a b -> Lens s t a b
pry (Lensy l) = l
-- Just …Run Code Online (Sandbox Code Playgroud) 从这种Getter类型开始
type Getter s a = forall r. (a -> Const r a) -> s -> Const r s
Run Code Online (Sandbox Code Playgroud)
我们需要一个额外的Monoid约束来获得Fold:
type Fold s a = forall r. Monoid r => (a -> Const r a) -> s -> Const r s
Run Code Online (Sandbox Code Playgroud)
但是Fold的实际和更一般的类型是
type Fold s a = forall f. (Contravariant f, Applicative f) => (a -> f a) -> s -> f s
Run Code Online (Sandbox Code Playgroud)
我了解这Contravariant是用来排除的Identity,因此确保我们只能获得价值。但是我不明白怎么Monoid r对应Applicative …