haskell - 如何使用镜头实现 unsafePartsOf
问题描述
我正在尝试unsafePartsOf
使用专用签名实现一个简单的版本:
unsafePartsOf :: Traversal s t a b -> Lens s t [a] [b]
在尝试了解它是如何工作的之后,我想出了这个(repl)。
myUnsafePartsOf :: Traversal s t a b -> Lens s t [a] [b]
myUnsafePartsOf traverse = lens getter setter
where
-- getter :: s -> [a]
getter s = s ^.. traverse
-- setter :: s -> [b] -> t
setter s xs = evalState (s & traverse %%~ assignElem) xs
assignElem _a = state $ \case
[] -> error "list not long enough"
(b : bs) -> (b, bs)
我认为使用lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
分离定义 getter 和 setter 将使它们更容易理解。
但是,此函数不进行类型检查,因为^..
operator ( toListOf
) 有一个(专门的)签名,toListOf :: Traversal' s a -> s -> [a]
说明原始s
和t
(以及a
and b
)将在哪里统一。
然后我尝试使用以下代码实现toListOf
(相同的 repl )的更通用版本:
toListOf :: Traversal s t a b -> s -> [a]
toListOf traverse s = execState (traverse getElem s) []
where getElem a = modify (a:)
但再次失败,因为b
由于()
使用modify
. 我知道我无法在中创建任意函数b
,getElem
所以这个函数是不可能的。
请注意,实际上可以partsOf
使用lens
类似的方式定义保险箱:
myPartsOf :: Traversal' s a -> Lens' s [a]
myPartsOf t = lens getter setter
where
getter s = s ^.. t
-- setter :: s -> [a] -> s
setter s xs = evalState (s & t %%~ assignElem) xs
assignElem a = state $ \case
[] -> (a, [])
(x : xs) -> (x, xs)
是否可以定义unsafePartsOf
使用lens
?如果是这样,我该怎么做?
解决方案
您可以定义getter
为:
getter s = s ^.. (\f -> Const . getConst . traverse (Const . getConst . f))
它似乎可以进行类型检查。
推荐阅读
- mysql - 如何设置列默认值以生成随机 6 位数字
- reactjs - 无法使用自定义对象数组 typescript-react
- php - laravel 8 播种,SQLSTATE[23000]:违反完整性约束:
- sql - 将点与 SQL/BigQuery 中的多边形匹配,使该点在多边形边界内至少 N 米(即不在边界附近)
- ocaml - 是 OCaml 中的整数构造函数吗
- javascript - 如何解决 React 应用程序和 Heroku 后端之间的 CORS (Access-Control-Allow-Origin) 错误
- java - 在Java中调用不同参数的方法
- r - 如何对具有最大列数和最小行数的数据框进行子集化
- javascript - 关闭打开的元素并显示新点击的元素
- javascript - 我必须在按钮上单击两次才能查看我的下拉列表。如何解决?