我试图通过在Haskell中实现它来了解镜头.我已经实现了view
如下组合器:
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
import Data.Traversable
type Lens s a = Functor f => (a -> f a) -> s -> f s
view :: Lens s a -> s -> a
view lens = getConst . lens Const
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试与它一起使用时,traverse
我收到以下错误消息:
Prelude> :load Lens.hs
[1 of 1] Compiling Main ( Lens.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t view traverse
<interactive>:1:6:
Could not deduce (Applicative f) arising from a use of ‘traverse’
from …
Run Code Online (Sandbox Code Playgroud) "透镜"和"部分透镜"在名称和概念上看起来相似.他们有什么不同?在什么情况下我需要使用其中一个?
标记Scala和Haskell,但我欢迎与任何具有镜头库的功能语言相关的解释.
我将在下一个Haskell项目中使用和学习Lens包.Data.Lens
当我发现这篇文章中提到van Laarhoven Lenses时,我几乎决定了这个Control.Lens
包.
我还不太了解差异,还没决定使用哪一个.您建议我在真实项目中学习/使用哪个软件包?
谢谢.
我正在和我一起工作Control.Lens
.我写的实际功能相当复杂,但为了这个问题的目的,我把它归结为一个最小的失败例子:
import Control.Lens
exampleFunc :: Lens s t a b -> String
exampleFunc _ = "Example"
Run Code Online (Sandbox Code Playgroud)
这无法编译,产生以下错误消息:
Illegal polymorphic or qualified type: Lens s t a b
Perhaps you intended to use -XRankNTypes or -XRank2Types
In the type signature for `exampleFunc':
exampleFunc :: Lens s t a b -> String
Run Code Online (Sandbox Code Playgroud)
为什么这是非法的?这似乎非常类似于以下,这确实编译:
import Data.Maybe
exampleFunc' :: Maybe (s, t, a, b) -> String
exampleFunc' _ = "Example"
Run Code Online (Sandbox Code Playgroud)
所以我假设差异在于定义Lens
.但是这种Lens
类型exampleFunc
的类型是非法的呢?我有一种潜在的怀疑,它与Functor
定义中的资格有关Lens …
我正在尝试习惯lens
Haskell 的库,发现自己在一些简单的问题上苦苦挣扎.例如,让我们说(为了方便起见)at
并且_1
具有以下类型(这至少是我理解它们的方式):
at :: Ord k => k -> Lens' (Map k v) (Maybe v)
_1 :: Lens' (a, b) a
Run Code Online (Sandbox Code Playgroud)
如何将这些镜头组合成以下类型的镜头:
maybeFst :: Ord k => k -> Lens' (Map k (a, b)) (Maybe a)
Run Code Online (Sandbox Code Playgroud) 我一直在阅读一个wreq教程:
镜头提供了一种聚焦于Haskell值的一部分的方法.例如,该
Response
类型具有responseStatus
镜头,其关注于服务器返回的状态信息.Run Code Online (Sandbox Code Playgroud)ghci> r ^. responseStatus Status {statusCode = 200, statusMessage = "OK"}
在
^.
操作者需要一个值作为第一个参数,一个透镜作为其第二个,并返回聚焦值的该部分上由透镜.我们使用功能组合构成镜头,这使我们可以轻松地专注于深层嵌套结构的一部分.
Run Code Online (Sandbox Code Playgroud)ghci> r ^. responseStatus . statusCode 200
我无法想出如何使用这个参数顺序完成的函数组合可以按顺序处理嵌套结构.
看:r ^. responseStatus . statusCode
可能是r ^. (responseStatus . statusCode)
或者(r ^. responseStatus) . statusCode
.
在第一个中我们构造了一个函数,它首先处理statusCode
(从记录中获取它Status
? - 因为我可以从显示的值中推导出来Status {statusCode = 200, statusMessage = "OK"}
),然后将它传递给responseStatus
必须处理响应状态的函数.所以,反过来说:实际上,状态代码是响应状态的一部分.
第二读对我来说也没有意义,因为它也首先处理状态代码.
haskell records function-composition higher-order-functions lenses
为什么我们需要Control.Lens.Reified?有什么理由我不能Lens
直接放入容器吗?reify
无论如何,意味着什么?
这里真的很简单.看完镜头的精彩介绍后:
http://www.youtube.com/watch?v=efv0SQNde5Q
我想我可能会尝试谈谈中的一个简单例子:
import scalaz.Lens._
fst.andThen(snd).set(((1,2),3),9)
Run Code Online (Sandbox Code Playgroud)
之后是这个错误
error: type mismatch;
found : scalaz.Lens[(Nothing, Nothing),Nothing]
required: scalaz.Lens[(Nothing, Nothing),C]
Note: Nothing <: C, but class Lens is invariant in type B.
You may wish to define B as +B instead. (SLS 4.5)
fst.andThen(snd).set(((1,2),3))
^
Run Code Online (Sandbox Code Playgroud)
有关如何使这项工作的任何想法?
给出以下代码:
case class Person(name :String)
case class Group(group :List[Person])
val personLens = GenLens[Person]
val groupLens = GenLens[Group]
Run Code Online (Sandbox Code Playgroud)
我如何从选择中"过滤掉"某些人,不是通过索引而是通过特定属性Person
,例如:
val trav :Traversal[Group, Person] = (groupLens(_.group) composeTraversal filterWith((x :Person) => /*expression of type Boolean here */))
Run Code Online (Sandbox Code Playgroud)
我只找到了这个filterIndex
函数,它只包含基于索引的列表中的元素,但这不是我想要的.
filterIndex
采用类型的函数: (Int => Boolean)
而且我要:
filterWith
(由名称构成),取a (x => Boolean)
,其中x具有lists元素的类型,即Person
在这个简短的例子中.
这似乎是如此实际和普遍,以至于我认为有人已经考虑过这一点而且我(我必须承认对这个问题的理解有限)不明白为什么不能这样做.
我是否遗漏了这个功能,它是否尚未实现,或者由于某种原因显然是不可能的(如果你有时间,请解释).
谢谢.
基于:
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参数化时,我无法使它工作.还有其他惯用的无样板解决方案吗?
谢谢!
lenses ×10
haskell ×7
scala ×4
scalaz ×3
haskell-lens ×2
calmm ×1
records ×1
shapeless ×1
traversable ×1