【问题标题】:How to compare lenses in Haskell如何在 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 实例。
  • 由于镜头只是功能,如果您将存储的东西去功能化怎么办?

标签: haskell lenses


【解决方案1】:

不要这样做。相反,使用通常的Equality 定义一个真实的数据类型,以及一个解释函数:

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 中关于“去功能化”的意思。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 2021-08-09
    • 2016-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多