我试图找出一种方法,如何以允许以下方式结合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) 我想写:
minimum $ map _x elems
Run Code Online (Sandbox Code Playgroud)
使用镜头.我想使用minimumOf镜头,但我无法弄清楚如何使用它的类型.
我正在寻找类似的东西
elems ^.. minimumOf x
Run Code Online (Sandbox Code Playgroud)
但它没有打字检查:
Prelude Control.Lens Data.Map> let elems = [(1,2),(3,4)] :: [(Double, Double)]
Prelude Control.Lens Data.Map> elems ^.. minimumOf _1
<interactive>:62:11:
Couldn't match type ‘Maybe a0’
with ‘[(Double, Double)]
-> Const (Data.Monoid.Endo [a]) [(Double, Double)]’
Expected type: Getting (Data.Monoid.Endo [a]) [(Double, Double)] a
Actual type: (a -> Const (Data.Monoid.Endo [a]) a) -> Maybe a0
Relevant bindings include it :: [a] (bound at <interactive>:62:1)
Possible cause: ‘minimumOf’ is applied …Run Code Online (Sandbox Code Playgroud) 我正在尝试为以下数据结构创建镜头.我正在使用lens-family.
data Tree = Tree {
_text :: String,
_subtrees :: [Tree]
} deriving (Show,Eq,Read,Generic)
Run Code Online (Sandbox Code Playgroud)
我想出于各种原因避免使用Template Haskell.首先,它似乎不适用于我的ghc版本(7.8.3),这是另一个(超出范围)问题.
为记录制作镜头并不难.
text :: Lens' Tree String
text f (Tree text' subtrees') =
(\text'' -> Tree text'' subtrees') `fmap` (f text')
subtrees :: Lens' Tree [Tree]
subtrees f (Tree text' subtrees') =
(\subtrees'' -> Tree text' subtrees'') `fmap` (f subtrees')
Run Code Online (Sandbox Code Playgroud)
但似乎镜头系列没有列表的默认镜头.我认为这是可能的.有lens包裹.这些是我失败的尝试:
import Lens.Family2
import Lens.Family2.Unchecked
-- List lenses
_last :: Lens [a] [a'] a a'
_last f l = …Run Code Online (Sandbox Code Playgroud) 我想尝试Monocle库.但我找不到基本语法的帮助资源.
总之,我需要Map[K,V] -> A具有光学器件的光学器件V -> A,我该如何定义它?
假设我有一些
import monocle.macros.GenLens
case class DirState(opened: Boolean)
object DirState {
val opened = GenLens[DirState](_.opened)
}
type Path = List[String]
type StateStore = Map[Path, DirState]
Run Code Online (Sandbox Code Playgroud)
接下来我遇到了我需要简单的地方StateStore => StateStore,所以我正在导入
import monocle._
import monocle.std._
import monocle.syntax._
import monocle.function._
Run Code Online (Sandbox Code Playgroud)
并尝试先定义:
def setOpened(path: Path): StateStore => StateStore =
at(path) composeLens DirState.opened set true
Run Code Online (Sandbox Code Playgroud)
到这里来
暧昧隐式的值:这两个方法
atMap在trait MapInstances类型[K, V]=> monocle.function.At[Map[K,V],K,V]和方法atSet在trait SetInstances类型的[A]=> monocle.function.At[Set[A],A,Unit] …
实际上我一直坚持功能编程代码风格和项目结构.用Java编程我知道在哪里放置我的逻辑,但我不熟悉函数风格.
实际上我尝试让我当前项目中的Scala类不可变.然后我想使用scalaz.Lens和scalaz.PLens来改变我的对象(实际创建新的).
在所有Lense示例中,人们将代码放在一个对象中,这扩展了App trait以简单地展示它是如何工作的.但在现实生活中的例子应该是一些适当的地方来写那些镜头.
在Java中,所有mutators和accessors都放在类本身中.但是对于镜头我不知道在哪里写它们.
将不胜感激任何建议
Monocle的选项具有以下访问功能(for Optional[C,A]):
getOption: C => Option[A]
set: A => C => C
Run Code Online (Sandbox Code Playgroud)
这与(部分)非对称数据镜头的原始定义不一致.我希望:
getOption: C => Option[A]
setOption: A => C => Option[C]
Run Code Online (Sandbox Code Playgroud)
这是什么原因?如何使用Monocle获得经典的局部镜片?在对镜头进行编程时,我发现确保整体设置比获取镜头要困难得多......
说我有一个嵌套的结构,如下所示:
data Bar = Bar { _id :: Integer, _bars :: [Bar] }
data Foo = Foo { _bars :: [Bar] }
Run Code Online (Sandbox Code Playgroud)
我有Foo一堆Bars与各种ids 在一起:
foo = Foo [Bar 1 [Bar 2], Bar 3 [Bar 4, Bar 5]]
Run Code Online (Sandbox Code Playgroud)
怎么办,可能使用的镜头,我修改foo,从而Bar 5成为Bar 6?
我知道我曾经fclabels做过这样的事情:
mkLabel ''Foo
mkLabel ''Bar
modify bars (\bars -> ...) foo
Run Code Online (Sandbox Code Playgroud)
但是条可以无限嵌套。如何找到并修改Bar具有指定ID的?
是否有更短/更清晰的方式编写以下代码片段:
fromMaybe "" $ fmap (^. fullName) (bi ^. bookerContact)
Run Code Online (Sandbox Code Playgroud)
这bi ^. bookerContact可能会导致Maybe Contact记录,这就是^. fullName需要fmap的原因.在嵌套遍历之后,如果我们最终得到一个Nothing我们用fromMaybe ""它来默认它为空字符串.
在Reason中思考一种在对象上定义简单镜头的方法。
我尝试..通过以下代码使用可扩展对象(在字段列表之前):
type hasName('a, 't) = {.. name: 't} as 'a;
type lens('s, 'v) = {
get: 's => 'v,
set: ('s, 'v) => 's,
};
let nameLens: lens(hasName('a, 't), 't) = {
get: s => s.name,
set: (s, v) => {...s, name: v},
}
Run Code Online (Sandbox Code Playgroud)
我收到“找不到记录字段名称”。错误,尽管类型hasName肯定应该有一个...我在这里做错了什么?
免责声明:我真的是Reason / OCaml的新手,所以我可能会错过一些显而易见的事情。
给定一般Getter类型
type Getter s a = forall f. (Contravariant f, Functor f) => (a -> f a) -> s -> f s
Run Code Online (Sandbox Code Playgroud)
我将如何为一对元组实现一个吸气剂?我想上面的类型代表了部分应用的功能,而缺少的部分正是让我感到困惑的地方。
除此之外,我不了解逆约束。可能是为了使镜头类型更像,但功能还不够吗?