gpt4 book ai didi

haskell - 如何使用Data.Functor.Invariant?

转载 作者:行者123 更新时间:2023-12-02 00:17:25 24 4
gpt4 key购买 nike

有人可以给我举个例子吗

invmap :: (a -> b) -> (b -> a) -> f a -> f b  

Invariant 有什么好处?

最佳答案

大多数情况下,人们使用Invariant。您想要这样做的原因是,如果您使用的类型中变量同时出现在协变和逆变位置。

newtype Endo a = Endo {appEndo :: a -> a}
newtype Foo a = Foo (Maybe a -> IO a)
data Bar a = Bar [a] (a -> Bool)

这些都不是仿函数逆变的实例,但它们都可以是不变的实例。

人们很少打扰的原因是,如果您需要对这种类型进行大量映射,通常最好将其分解为协变和逆变部分。每个不变仿函数都可以用 Profunctor 来表示:

newtype FooP x y = FooP (Maybe x -> IO y)
data BarP x y = Bar [y] (x -> Bool)

现在

Endo a ~= (->) a a
Foo a ~= FooP a a
Bar a ~= BarP a a
-- So we'd likely write newtype Bar a = Bar (BarP a a)

如果您将 newtypedimap 展开到底层 Profunctor 上,然后再次将其包裹起来,通常会更容易看到发生了什么而不是乱搞 invmap

<小时/>

我们如何将Invariant仿函数转换为Profunctor?首先,让我们处理总和和乘积。如果我们可以将fg转为仿函数fpgp,那么我们一定可以将f :+: gf :*: g 转换成等价的仿函数和和积。

作曲怎么样?这有点棘手,但不多。假设我们可以将 fg 转换为仿函数 fpgp。现在定义

-- Compose f g a ~= ComposeP fp gp a a
newtype ComposeP p q a b = ComposeP (p (q b a) (q a b))
instance (Profunctor p, Profunctor q) => Profunctor (ComposeP p q) where
dimap f g (ComposeP p) = ComposeP $ dimap (dimap g f) (dimap f g) p

现在假设您有一个函数类型; f a -> g a。这看起来像 fp b a -> gp a b

我认为这应该涵盖大多数有趣的案例。

关于haskell - 如何使用Data.Functor.Invariant?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48708805/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com