在 Prolog 中玩弄镜头。镜头是一种显微镜,可以放大结构并以功能方式进行一些读取或写入。基本上我的出发点是以下 Prolog 中 setter 和声明性 getter 的建模:
消气:只是<closure>,
被称为call(<closure>, X, Y),这将检索该值Y从X。
声明式设置器:相同<closure>但使用不同的元数,
称为 as call(<closure>, X, Y, Z),这将X通过一个新值更新 并Y给出一个新的Z。
我很快就得出了镜头合成运算符 @ 的定义,它可用于将两个镜头组合成一个新镜头,仅基于它们的闭合。附录中提供了一个示例和定义。但根据这篇文章,镜头可以简单地合成。
在我看来,当某些东西是合成的时,它可以很容易地通过 DCG 建模。我可以按如下方式为 getter 执行此操作,但我还没有找到为声明性 setter 执行此操作的方法:
/* Getter composition as DCG */
@(C1, C2) -->
call(C1),
call(C2).
Run Code Online (Sandbox Code Playgroud)
我将如何在 DCG 中对 setter 组合进行建模?这是可能的,也许会改变 getter 和 declarative setter 如何建模的初始假设,以便结果只是组合?
此致
附录:以下是一些 setter 和 getter 的示例:
/* …Run Code Online (Sandbox Code Playgroud) 我想做的是将字段描述符定义为json 的field1.field2[1].field3访问值two:
{
"field1": {
"field2": [
{
"field3": "one"
},
{
"field3": "two"
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用applyDynamicand做到这一点root.field1.field2.index(1).field3,但是有没有办法使用字符串来创建这样的镜头?
如果我有一个newtype
newtype Foo = Foo Int
Run Code Online (Sandbox Code Playgroud)
有没有一种自动获取 的方法Iso' Foo Int?
我看到我可以使用makeLenses ''Foo,但我不知道生成的 iso 的名称是什么。
克里斯·彭纳 (Chris Penner) 的这篇文章谈到了“枯萎的光学”;可用于从结构中过滤项目的光学元件。
本文对这些光学器件使用以下“Van Laarhoven”表示:
type Wither s t a b = forall f. Alternative f => (a -> f b) -> s -> f t
Run Code Online (Sandbox Code Playgroud)
大多数(如果不是全部)Van Laarhoven 光学具有等效的 profunctor 表示。例如镜头:
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
Run Code Online (Sandbox Code Playgroud)
相当于:
type Lens s t a b = forall p. Strong p => p a b -> p s t
Run Code Online (Sandbox Code Playgroud)
是否Wither也有 Profuctor 代表?如果是这样,那是什么?
我正在尝试使用 Haskell 中的透镜和棱镜访问嵌套记录:
import Data.Text (Text)
import Control.Lens.TH
data State = State
{ _stDone :: Bool
, _stStep :: StateStep
}
data StateStep
= StatePause
| StateRun
{ _stCounter :: Int
, _stMMistake :: Maybe Text
}
makeLenses ''State
makeLenses ''StateStep
makePrisms ''StateStep
main :: IO ()
main = do
let st = State False $ StateRun 0 Nothing
-- works, but the `_2` seems weird
mMistake = st ^? stStep . _StateStepRun . _2 . _Just
-- why not …Run Code Online (Sandbox Code Playgroud) 假设我有以下内容:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Book = Book {
_author :: String,
_title :: String
} deriving (Show)
makeLenses ''Book
data Location = Location {
_city :: String,
_state :: String
} deriving (Show)
makeLenses ''Location
data Library = Library {
_location :: Location,
_books :: [Book]
} deriving (Show)
makeLenses ''Library
lib :: Library
lib = Library (Location "Baltimore" "MD") [Book "Plato" "Republic", Book "Aristotle" "Ethics"]
Run Code Online (Sandbox Code Playgroud)
我试图通过组合镜头来了解通过多层向下延伸的各种方法.我知道如何做这些操作:
-- returns "Baltimore"
lib ^. location . city
-- …Run Code Online (Sandbox Code Playgroud) 我有一个深度嵌套的数据结构,我正在使用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吗?
从数据容器(例如案例类)中提取类型的最佳方法是什么.
例如,如果我有type Tagged[U] = { type Tag = U}标记类型trait PID,标记为Int type ProductId = Int with Tagged[PID]或scalaz样式,type ProductId = Int @@ PID并说明产品type Name = String @@ PName等中的其他字段和包含产品属性的数据容器;
case class Product(pid: ProductId, name: Name, weight: Weight)
Run Code Online (Sandbox Code Playgroud)
如何在A => B不诉诸反射的情况下编写通用的提取器样式方法?
原因是我想在运行时从Product容器中动态提取字段.即,用户传递他们想要提取的产品的属性.
即如果我想动态获取ProductId,我可以编写一个接受类型并返回值的方法,例如
trait Extractor[A] {
def extract[B](i: A): B = //get type B from the Product class
}
Run Code Online (Sandbox Code Playgroud)
或者我是在复杂的事情.
我可以编写简单的提取器类,它采用A => B函数并为每种类型定义它;
trait Getter[A, B] {
def extract(i: A): B …Run Code Online (Sandbox Code Playgroud) 抱歉这个措辞不好的标题,但我甚至不知道如何正确地问它.
我怎么能这个呢?
instPublicIP :: Instance -> Maybe Text
instPublicIP inst =
inst ^. insNetworkInterfaces ^? ix 0 . iniAssociation . _Just . iniaPublicIP . _Just
Run Code Online (Sandbox Code Playgroud)
进入这个
instPublicIP' :: Lens' Instance (Maybe Text)
instPublicIP' = insNetworkInterfaces ^? ix 0 . iniAssociation . _Just . iniaPublicIP . _Just
Run Code Online (Sandbox Code Playgroud)
当我尝试时,我收到以下错误:
Main.hs:198:3:
Couldn't match expected type ‘(Maybe Text -> f (Maybe Text))
-> Instance -> f Instance’
with actual type ‘Maybe Text’
Relevant bindings include
instPublicIP' :: (Maybe Text -> f (Maybe Text))
-> …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?
lenses ×10
haskell ×7
haskell-lens ×5
scala ×2
circe ×1
composition ×1
dcg ×1
generics ×1
json ×1
profunctor ×1
prolog ×1
record ×1
scalaz ×1
shapeless ×1