如何在 Haskell 中比较镜头
Posted
技术标签:
【中文标题】如何在 Haskell 中比较镜头【英文标题】:How to compare lenses in Haskell 【发布时间】:2022-01-04 17:39:28 【问题描述】:我对镜头的 Eq 实例很好奇。 镜头是功能。很难比较任意函数,但镜头是一类特殊的函数。
我正在考虑为s
类型使用 QuickCheck 任意实例:
lensesAreEqual ::
(Arbitrary a, Eq a) =>
Lens' s a ->
Lens' s a ->
Gen Bool
lensesAreEqual l1 l2 =
and <$> forM [0..100] $ \_ -> do
s <- arbitrary
pure $ s ^. l1 == s ^.l2
我可以将 lensAreEqual monad 放在 unsafePerformIO 后面以获得整洁的 Eq 实例。
有人知道更好的解决方案吗?
【问题讨论】:
您可以轻松地为任何功能执行此操作。它可能在务实的意义上起作用,以确定 2 个函数是否“似乎相等”。但是我非常不愿意在带有 UnsafePerformIO 的纯代码中使用它。至少从理论上讲,这可以告诉您相同的 2 个函数在某些运行中相等,但在其他运行中不相等! 一般来说,没有合适的方法来做到这一点。你为什么还要这样做? @JosephSible-ReinstateMonica 我想概括 shim 以在基于砖的应用程序中滚动多个列表小部件,并在 Name 中携带镜头以从事件处理程序中的应用程序状态中选择特定列表。名称应该有 Ord 实例。 由于镜头只是功能,如果您将存储的东西去功能化怎么办? 【参考方案1】:不要这样做。相反,使用通常的Eq
uality 定义一个真实的数据类型,以及一个解释函数:
data ItemType = Weapons | Armor | Potions deriving (Eq, Ord, Read, Show)
data AppState a = AppState
_weapons :: [a]
, _armor :: [a]
, _potions :: [a]
, _activeType :: ItemType
deriving (Eq, Ord, Read, Show)
toLens :: ItemType -> Lens (AppState a) (AppState b) [a] [b]
toLens Weapons = weapons
toLens Armor = armor
toLens Potions = potions
(这就是 cmets 中关于“去功能化”的意思。)
【讨论】:
以上是关于如何在 Haskell 中比较镜头的主要内容,如果未能解决你的问题,请参考以下文章