typescript - 函数式编程/光学概念,它采用部分对象并使用镜头和遍历返回“填充”对象?
问题描述
(编辑我正在使用monocle-ts,但是如果使用 monocle-ts 是不可能的(因为作者甚至说它只是 Scala 原始 Monocle 的部分端口)但是如果在另一个光学包中有任何语言的东西,我愿意将这些想法移植到 TypeScript。)
假设我有一个辅助类型Partial<A>
,它表示一个记录,该记录具有类型的部分或全部,但没有非成员A
。(所以如果A = { foo: number, bar: string }
then Partial<A> = { foo?: number, bar?: string }
)(编辑这是 Typescript 的内置 Partial 实用程序类型。)
我从
interface Parent {
xs: Child[]
}
interface PartialParent {
partialxs: Partial<Child>[]
}
declare function fillInTheGaps(x: Partial<Child>):Child
假设我已经组合了一个镜头并遍历组合 ( composedTraversal
) 以便它聚焦于 partialxs
fromPartialState
然后作为一个数组遍历它。这将是一个Traversal<PartialState, Partial<Child>>
.
还假设我有一个declare const fn = (x:Partial<Child>):Partial<Child>
然后我可以应用于fn
所有孩子,composedTraversal.modify(fn)(partialState)
这将产生一个新PartialState
的fn
应用于所有partialxs
.
是否有一些概念可以让我“扩大”或“转换”这个遍历到不同的东西,以便我可以组成镜头和遍历并使用fillInTheGaps
,这样我就可以传入PartialState
并取回 a State
?
忽略我的语法是 TypeScript,我添加了 monocle-scala 标签,因为如果这个概念存在,我想它在 Monocle 库中,我可以将这些知识翻译到我正在使用的库中。
编辑激发这个问题的问题是我在 Redux 应用程序中有一个表单输入,用户输入数据但大多数不是必需的。INPUT 在编译时是未知的(它们是从 RESTful API 查询中重试的),所以我不能将模型表示为
interface Model {
foo?: string[]
bar?: string[]
}
相反,它表示为
interface Model {
[index:string]: string[]
}
我还可以从 RESTful 服务器获取默认模型。所以我将这些建模为Parent
(来自服务器的Partial<Parent>
内容)和(代表用户在应用程序中的输入)。
在进行一些计算之前,我需要为缺少的道具折叠默认值。这是我fillInTheGaps
上面引用的函数。
希望通过我的代码中的类型来强制执行此操作,并且因为我已经编写了很多光学元件,所以重用其中的一些。实际上,我编写了一个镜头和遍历来对这些数据执行其他操作。myLens.compose(myTraversal).modify(fn)
接受 aPartial<State>
并返回 aPartial<State>
但我希望将这些组合起来最终得到一个接受部分并返回整体的函数。
我显然可以只写const filler: (Partial<State>):State = myLens.compose(myTraversal).modify(fillInTheGaps)
然后//@ts-ignore
在它上面扔一个并且知道它会起作用,但这似乎,呃,脆弱。
解决方案
我认为,您可能想要的是多态遍历或PTraversal<S, T, A, B>
.
ATraversal<S, A>
说,“如果我有一个函数A => A
,我可以用它modify
来获得一个函数S => S
,它使用原始函数来修改所有
A
出现在S
”中的 s。
相比之下,aPTraversal<S, T, A, B>
说,“如果我有一个函数A => B
,我可以用它modify
来获取一个函数S => T
”,这会将所有A
s转换S
为B
,从而产生 a T
。
助记符的类型参数为PTraversal
:
S
的来源PTraversal
T
的“修改”来源PTraversal
A
的目标PTraversal
B
的“修改”目标PTraversal
PTraversal
s 很有用,因为它们让您可以编写如下内容:
PTraversal<Array<A>, Array<B>, A, B>
Array
让您在更改元素类型的同时遍历。
在您的具体情况下,您提到有两个功能:
declare function fillInTheGaps(x: Partial<Child>):Child
declare function fn(x: Partial<Child>):Partial<Child>
这些可以组合在一起以产生单个功能:
function transformAndFill(x: Partial<Child>): Child {
return fillInTheGaps(fn(x));
}
然后,您需要编写一个PTraversal<PartialState, State, Partial<Child>, Child>
.
这将支持用 a 作曲,以与所做的大致相同的方式Lens
制作一个新的。PTraversal
Traversal
这应该是可行的,我认为从您的问题来看,如果您可以将 every Partial<Child>
in转换PartialState
为 aChild
您应该能够制作State
.
PTraversal
存在于 Monocle(Scala 库)中,但不幸的是,它看起来不像是它monocle-ts
:所以不幸的是,您必须编写大量的光学库代码才能支持这一点。
推荐阅读
- python - 无法从数据集中获取数据(解包的值太多(预期 2))
- python-3.x - Python字典:迭代列表中的值
- c++ - 如何重命名 CodeBlocks 中整个 C++ 代码的变量名?
- html - CSS中的背景效果
- apache-superset - 获取收藏状态时出错:尝试在超集中获取资源时出现 NetworkError
- javascript - Selenium 可以定位一个元素,但它似乎是返回一个空对象,非常意外
- java - Javafx 如何重新启动应用程序?
- python-3.x - Python 如何从python中的句子中获取最后一个单词?
- sqlite - 使用外键创建表时出现语法错误
- c# - 无法使用 IDistributedCache 缓存 AuthenticateResult 条目