本着以下问题的精神:
我现在正在寻找一种方法将多个Getter组合成一个单一的Fold,以便如下所示:
('a','b','c','d') ^.. (_1 <> _2 <> _3)
Run Code Online (Sandbox Code Playgroud)
会导致这个:
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)
但上面的代码实际上失败并显示以下消息:
No instance for (Monoid
(Accessor (Endo [Char]) (Char, Char, Char, Char)))
arising from a use of `<>'
Run Code Online (Sandbox Code Playgroud)
那么我该如何实现呢?这可能吗?
考虑具有以下(伪)签名的"组合"函数:
(a1 -> a2 -> ... -> an -> r) ->
(s -> ai) ->
a1 -> a2 -> ... -> ai -> ... an -> r
where i in [1..n]
Run Code Online (Sandbox Code Playgroud)
当然我们不能在Haskell中编写上面的内容,但这是一个具体的例子:
f4change3 ::
(a1 -> a2 -> a3 -> a4 -> r) ->
(s -> a3) ->
a1 -> a2 -> s -> a4 -> r
f4change3 f g x1 x2 x3 x4 = f x1 x2 (g x3) x4
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,n
arity的每个函数都有一组函数n
,因此我们需要的函数数量与arity呈二次方式增长.
我可以写出我需要的那些,但首先,我不想重新发明轮子,所以很高兴知道库是否已经完成了这个.但是,虽然我几乎没有使用镜头,但我已经阅读了一些关于它们的内容,这种问题似乎正好在他们的盟友身上,但我不确定该怎么做.如果可能的话,一些示例代码会很棒.
我的问题非常类似于如何使用带镜头的monadic功能进行修改?作者问这样的事情是否存在
overM :: (Monad m) => Lens s t a b -> (a -> m b) -> s -> m t
Run Code Online (Sandbox Code Playgroud)
答案是mapMOf
mapMOf :: Profunctor p =>
Over p (WrappedMonad m) s t a b -> p a (m b) -> s -> m t
Run Code Online (Sandbox Code Playgroud)
我正在尝试实现一个MonadState
使用monadic函数修改状态的函数:
modifyingM :: MonadState s m => ASetter s s a b -> (a -> m b) -> m ()
Run Code Online (Sandbox Code Playgroud)
示例没有modifingM
:
{-# LANGUAGE TemplateHaskell #-}
module Main where …
Run Code Online (Sandbox Code Playgroud) 我阅读了使用Circe Optics的Circe文档给出的示例。文档中的示例非常简单,因为到节点的路径很容易找到。
在我的情况下,json看起来像
import io.circe._, io.circe.parser._
val json = """[["a",{"entity":["foo"]}],["b",{"entity":["bar"]}]]"""
Run Code Online (Sandbox Code Playgroud)
这是有效的json,我可以解析使用 parse(json)
但是,我该如何编写镜头以便提取所有“ foo”,“ bar”。
根据其文档,Haskell 的lens
库_1
为元组提供了一个镜头。
对于数据记录,还有其他几个功能,例如makeLenses
,根据记录的字段名称自动生成镜头。
不幸的是,我正在处理没有命名字段的数据类,这makeLenses
对我来说意味着意义。这让我感到奇怪。_1
看起来很方便,但正如其文档中暗示的那样,似乎不适用于数据类。是否有同等程度的便利?
> :set -package lens
> import Control.Lens
> (1,2) ^. _1
1
> data Bar = Bar String deriving Show
> bar = Bar "abc"
> bar ^. _1
<interactive>:271:1: error:
• Non type-variable argument in the constraint: Field1 Bar Bar b b
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall b. Field1 Bar Bar b b => …
Run Code Online (Sandbox Code Playgroud) 我正在用Ruby制作一个镜头组合器,我无法弄清楚它的普遍接受的名称是什么.未知函数组成两个具有相同源类型和目标类型的镜头(使用 Benjamin C. Pierce的术语)是一个哈希映射.未知功能接收这两个镜头并返回一个新镜头,它与原始镜头具有相同的光源类型和目标类型.
它看起来像这样(Ruby语法):
lens_a.get(source)
> {:title => "some title"}
lens_b.get(source)
> {:description => "some description"}
new_lens = unknown_function(lens_a, lens_b)
new_lens.get(source)
> {:title => "some title", :description => "some description"}
Run Code Online (Sandbox Code Playgroud)
我正在尝试构建的组合器的图表可以在本演示文稿的幻灯片18上看到(幻灯片的标题是"合并?").
我看过Haskell的镜头文档(我可以理解其中的一小部分),但我无法弄清楚这是哪个组合器.
上面的unknown_function的标准名称是什么?如果这个镜头没有标准名称,是否有一些标准功能可以组成它?如果没有,我可能只是称它为合并.
我有一个类似于以下内容的JSON Blob:
[
{
"version": 1
},
{
"version": "3"
},
...
]
Run Code Online (Sandbox Code Playgroud)
请注意,有些版本是数字,有些是字符串。我想获取版本列表。我可以使用以下镜头组合来提取数字版本:
v1 :: [String]
v1 = obj ^.. AL.values . AL.key fieldName . AL._Number . to show
Run Code Online (Sandbox Code Playgroud)
然后下面提取字符串
v2 :: [String]
v2 = obj ^.. AL.values . AL.key fieldName . AL._String . to T.unpack
Run Code Online (Sandbox Code Playgroud)
但是,如何通过一次遍历列表来获得版本列表?是否有任何镜头组合器需要镜头AL._Number . to show
并AL._String . to T.unpack
返回组合的吸气剂,以便如果第一个失败,则尝试第二个?msum
镜片像什么?
我想以这种方式使用元组和镜头:
myfct :: ReaderT (a,b,c,d,e) m a -> ReaderT (a,c,d) m a
myfct = zoom ...
Run Code Online (Sandbox Code Playgroud)
能够将输入元组修改为它的一个子集...
伪代码将是这样的:
zoom (_1,_3,_4)
Run Code Online (Sandbox Code Playgroud) 是否有一个类似镜头的物体的通用名称/类型不满足取出你放入的东西的特性?例如listLength :: Lens [a] Int
,如果您输入的长度比源列表的长度短,则会得到一个缩短的列表,但是如果您输入的长度更长,则原始长度将被保留。
我对镜头的 Eq 实例很好奇。镜头是功能。很难比较任意函数,但镜头是一类特殊的函数。
我正在考虑将 QuickCheck 任意实例用于s
类型:
lensesAreEqual ::
(Arbitrary a, Eq a) =>
Lens' s a ->
Lens' s a ->
Gen Bool
lensesAreEqual l1 l2 =
and <$> forM [0..100] $ \_ -> do
s <- arbitrary
pure $ s ^. l1 == s ^.l2
Run Code Online (Sandbox Code Playgroud)
我可以将 LensAreEqual monad 放在 unsafePerformIO 后面以获得简洁的 Eq 实例。
有人知道更好的解决方案吗?
我有一个Kafka主题,大约有300万条记录。我想从中选择具有特定参数的单个记录。我一直在尝试使用Lenses进行查询,但是无法形成正确的查询。以下是1条消息的记录内容。
{
"header": {
"schemaVersionNo": "1",
},
"payload": {
"modifiedDate": 1552334325212,
"createdDate": 1552334325212,
"createdBy": "A",
"successful": true,
"source_order_id": "3411976933214",
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我想过滤出具有特定source_order_id的记录,但无法找出正确的方法。我们已经尝试通过镜头以及Kafka Tool。
我们在镜头中尝试过的示例查询如下:
SELECT * FROM `TEST`
WHERE _vtype='JSON' AND _ktype='BYTES'
AND _sample=2 AND _sampleWindow=200 AND payload.createdBy='fms'
Run Code Online (Sandbox Code Playgroud)
此查询有效,但是,如果我们尝试使用如下所示的源ID,则会出现错误:
SELECT * FROM `TEST`
WHERE _vtype='JSON' AND _ktype='BYTES'
AND _sample=2 AND _sampleWindow=200 AND payload.source_order_id='3411976911924'
Error : "Invalid syntax at line=3 and column=41.Invalid syntax for 'payload.source_order_id'. Field 'payload' resolves to primitive type STRING.
Run Code Online (Sandbox Code Playgroud)
通过自定义使用者使用所有300万条记录,然后对其进行遍历,这对我来说似乎并不是一种优化的方法,因此,寻找针对这种用例的任何可用解决方案。
Play框架是否默认包含任何镜头支持?像Monocole或Scalaz 那样的东西.也许我不知道有推荐的替代方法(及其基本原理).
场景:我有一个案例类的不可变的,深度嵌套的对象,我想用一个在对象中某处更改的字段来复制它.
我正在寻找这样做非常简单而不需要太多样板,就像像Monocole那样的镜头库.
我很惊讶Play框架内置了任何支持.我错过了什么吗?如果没有,是否有任何已知的支持计划?