我正在编写一个函数,可以在一系列任意符号中进行搜索.我想使它足够通用,以便它可以在列表,Foldable
s以及ByteString
s和Text
s上运行.将其概括Foldable
为简单.但是如何包含ByteString
s和Text
s?当然我可以转换ByteString
成一个列表,然后调用我的功能,但我会失去所有的优势ByteString
.
举一个具体的例子,假设我们想要制作直方图函数:
import Control.Monad.State
import qualified Data.Foldable as F
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Word
import qualified Data.ByteString as B
import qualified Data.Text as T
type Histogram a = Map a Int
empty :: (Ord a) => Histogram a
empty = Map.empty
histogramStep :: (Ord a) => a -> Histogram a -> Histogram a
histogramStep k = Map.insertWith (+) k …
Run Code Online (Sandbox Code Playgroud) 我正在使用镜头包,并一直认为必须有一个简单的解决方案来解决以下问题.假设我At
的值类型有一些地图(或任何实例)和镜头,即
aMap :: Map Int a
aLens :: Simple Lens a b
Run Code Online (Sandbox Code Playgroud)
我想要一个吸气剂
g :: Getter (Map Int a) (Maybe b)
Run Code Online (Sandbox Code Playgroud)
这是因为我经常想做这样的事情
x :: Maybe b
x = aMap^.at 3.g.aLens
Run Code Online (Sandbox Code Playgroud)
当然,预期的语义是Just
在at
查找时以及Nothing
其他方式获取值.
当一个人设置而不是代替traverse
工作g
,即
newMap = at 3.traverse.aLens .~ whatever $ aMap
Run Code Online (Sandbox Code Playgroud)
但是当你到达时却没有.是否有一些现成的镜头我刚刚错过的库,或者是否有另一种简单的方法可以在单个表达式中实现这一点?
镜头如何处理脱糖字段是关键字的情况?我似乎记得读过一些特别的东西,但是我不记得我在哪里阅读它或者"镜头"访问者的名字最终会是什么.
考虑以下:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.IO.Class (liftIO)
import Data.Maybe
import Data.Aeson
import Data.Aeson.TH
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as LC8
import qualified Data.Text.Lazy.Encoding as TLE
data Typ = Typ {
_fld1 :: BS.ByteString
, _type :: Int
} deriving (Show)
$(deriveJSON tail ''Typ)
$(makeLenses ''Typ)
main = do
print $ typ^.fld1
print $ typ^.getType
where
jsonTyp = "{\"fld1\": \"Test\", \"type\": 1 }"
typ' = …
Run Code Online (Sandbox Code Playgroud) 我有一个[(a, Maybe b)]
,并希望获得一个[(a, b)]
,所有对,其中第二个元素被Nothing
过滤掉.是否有一种简洁的方法来描述使用镜头的操作?
基于:
import shapeless._
case class Content(field: Int)
lens[Content] >> 'field
Run Code Online (Sandbox Code Playgroud)
我正在尝试制作镜头创建方法,其中包括:
def makeLens[T <: Product](s: Symbol) = lens[T] >> s
Run Code Online (Sandbox Code Playgroud)
但这似乎并不明显.有可能吗?
如果没有,我想要实现的最终结果是使用案例类内容更新嵌套映射的通用方法,例如:
import scalaz._
import Scalaz._
import PLens._
import shapeless._
import shapeless.contrib.scalaz._
def nestedMapLens[R, T <: Product](outerKey: String, innerKey: Int, f: Symbol) =
~((lens[T] >> f).asScalaz) compose mapVPLens(innerKey) compose mapVPLens(outerKey)
Run Code Online (Sandbox Code Playgroud)
当用T和f参数化时,我无法使它工作.还有其他惯用的无样板解决方案吗?
谢谢!
据我了解,每个 van Laarhoven 光学类型都可以通过类型构造函数的约束来定义:
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
-- etc.
Run Code Online (Sandbox Code Playgroud)
如果我们选择Monad
作为约束,它是否以有意义的方式形成某种“光学”?
type Something s t a b = forall f. Monad f => (a -> f b) -> s -> f t
Run Code Online (Sandbox Code Playgroud)
我的直觉是,Monad
约束可能过于严格,无法从这样的结构中获取任何值:由于Const
函子不是 a Monad
,我们无法通过专门化 …
我有一个嵌套的case
类结构List
为简单起见,请使用以下示例 -
case class Address(street: String, city: String, state: String, zipCode: Int)
case class Person(firstName: String, lastName: String, addresses: List[Address])
case class Department(people: List[Person])
Run Code Online (Sandbox Code Playgroud)
说有List[Department]
; 现在,如果我想List[Department]
通过过滤Address
每个Person
没有特定zipCode
值的新东西来创建一个新的; 传统上我们可以做到以下
def filterPersonsByAddress(dlist: List[Department]): List[Department] = {
dlist.map { d =>
val people = d.people.map { p =>
p.copy(addresses = p.addresses.filterNot(_.zipCode == 38978))}
d.copy(people=people)
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法不具备性能,因为取决于嵌套级别,它可以是Big O(n ^ 2)或Big O(n ^ 3);
我试图通过Monocle学习镜头.到目前为止,我学到的是当你必须"修改"一个深层嵌套的case
类结构但尚未找到一种方法根据条件"切断"嵌套结构的某些部分并返回一个新结构时,镜头很有用.这可能是通过Monocle吗?此外,我不确定Lenses是否能够帮助实现更好的Big O时间?
甲棱镜为聚焦到联产品类型的光学部件,而仿射遍历是一种光学器件的可聚焦于0 1的元件,即,AffineTraversal s t a b
是同构的(s -> Maybe a, (s, b) -> t)
.据我所知,如果镜头由棱镜组成,我们会得到一个仿射遍历,只要使用适当的棱镜编码.
我感兴趣的是将Maybe
那个(幼稚)配方移动到设置器侧而不是吸气器侧,这样我就可以使用一个总是提取一个元素的光学元件,但可能无法将它放回去.
我的用例与细化类型有关.想象一下,我们有一个类型A
及其细化B
(B ? A
).然后有一个棱镜refined :: Prism' A B
:一个A
可能或可能不是有效的B
,但每个B
都可以re
进入一个A
.结合了Lens' C A
有refined
,我们有一个仿射遍历.在另一个方向上,可以想象一个光学元件unrefined
比一个光学元件更聪明re refined
:如果它是有效的,A
可以变成一个光学元件,或者如果它不是,则可以变成光学元件.现在,如果我们结合了有,我们有我们的双仿射穿越:它可以随时获得从,但放回任何旧的可能违反的不变和产量,而不是.可以以类似的方式确保更复杂的不变量.Just b
B
Nothing
Lens' C B
unrefined
A
C
A
C
Nothing
Just c
有趣的是,Scala 的单片机 …
爱德华·克梅特(Edward Kmett)的光学图书馆;Control.Lens定义了大量类型。
其中大多数具有相对自我解释的名称,例如Traversal和Fold。
它还定义了一些名称不那么明显的类型,例如Bazaar
在“义卖市场”页面上:
aka索引的笛卡尔商店comonad,索引的Kleene商店comonad或索引的FunList。
...
通常,集市上有很多商店,您可以轻松添加更多。
我无法弄清楚Market类型名称背后的原因。我认为这在某种程度上也与商店monads / comonads有关?它是否正确?
我在使用 Lenses 和 Maps 时遇到了一些困难。我有看起来像这样的地图Map String (Map String Int)
。这些是多维数组,我通常使用已知维度设置它们。我经常想读取和更新这些 Maps 的元素,但不想添加或删除元素。
我想要一个类似于ix "k1" . ix "k2"
允许我执行以下操作的光学器件:
myfunc :: Map String (Map String Int) -> ()
myfunc m =
let m' = m & ix "k1" . ix "k2" %~ (+1)
v = m ^. ix "k1" . ix "k2"
in ()
Run Code Online (Sandbox Code Playgroud)
不幸的是,我不能使用ix "k1" . ix "k2"
,v = m ^. ix "k1" . ix "k2"
因为Int
它不是 Monoid无法编译。一般来说,我不能有这个 Monoid 限制,因为我通常在我的地图中持有相当复杂的值(比如一些复杂的状态 ADT)。(我猜这个 Monoid 限制是存在的,所以 …
lenses ×10
haskell ×8
haskell-lens ×2
scala ×2
bytestring ×1
fold ×1
scalaz ×1
shapeless ×1
terminology ×1
text ×1