这个类似functor-ish标签的类型类的名称是什么?

时间:2016-05-04 22:20:00

标签: haskell typeclass functor

我注意到我有很多函数可以为我的值添加某种标记。例如,请考虑以下两种数据类型:

data Named a = Named String a                                                   
data Colored a = White a | Black a

以及一些使用它们的函数:

name :: Foo -> Named Foo
color :: Named Foo -> Colored (Named Foo)

在某些时候我开始使用许多嵌套的“标签”这样的函数,所以我想知道我是否可以概括它以使其更易于管理。所有这些都可能很适合PureScript的行多态,但我们在这里讨论的是Haskell。无论如何,这是我想出的:

class Tag f where                                                  
    separate :: f a -> (forall b. b -> f b, a)

法律将是这样的:

fx = let (f, x) = separate fx in f x

或者没有类型检查但更优雅的版本:

uncurry ($) . separate = id

Tag也可以成为Functor的子类,只要

fmap g fx = let (f, x) = separate fx in f (g x)

示例数据类型的实例如下:

instance Tag Named where
    separate (Named name x) = (Named name, x)

instance Tag Colored where
    separate (White x) = (White, x)
    separate (Black x) = (Black, x)

......以及其他一些一般情况:

instance Tag Identity where
    separate (Identity x) = (Identity, x)

instance (Tag f, Tag g) => Tag (Compose f g) where
    separate (Compose fgx) =
        let (f, gx) = separate fgx in
        let (g, x) = separate gx in
        (Compose . f . g, x)

使整个类型类实际有用的是这个函数:

reorder :: (Tag f, Tag g) => f (g a) -> g (f a)
reorder fgx =
    let (f, gx) = separate fgx in
    let (g, x) = separate gx in
    g (f x)

它看起来像一些明显的成语,所以它必须已被社区所知。如果您不知道要搜索的内容的名称,并且Hoogle没有回复,那么Google就不是很有帮助。

所以在这里,我正在寻找一个名字,甚至可能还有一些图书馆,看看我还能做些什么呢。

1 个答案:

答案 0 :(得分:0)

user2407038's comment确实引起了人们的注意,因为您最终想要表达的概念归结为对某些对函子同构的函子-毕竟,对是具有其他某些东西的价值附上。从这个有利的角度来看,还有一些可能有趣的额外注意事项。

为了方便起见,我假设您的TagFunctor(您提到的相关条件由参数确定),并通过将forall b. b -> f b替换为{同构f ()。然后,我们可能会有:

separate :: Tag f => f a -> (f (), a)

遵守法律:

slot . separate = id

其中左倒数为:

slot :: Functor f => (f (), a) -> f a
slot (sh, a) = fmap (const a) sh

通过添加slot必须是实词的要求(就您的用例而言,这是完全明智的),slot升级为完全反,从而使我们在{ {1}}和f a

这些功能至少存在于生态系统中的一个位置:the adjunctions package

(f (), a)

Hask / Hask左伴随是同构的,以配对函子,双重性是Hask / Hask右伴随是Representable的同义,即同构对函子。从某种意义上来说,dfeuer's suspicion是合理的,尽管附加语并没有给我们与splitL :: Adjunction f u => f a -> (a, f ()) unsplitL :: Functor f => a -> f () -> f a Distributive的左伴相伴。这是它们的草图,其中包含虚构的名称:

Representable

关于class Traversable t => Lone t where codistribute :: Functor f => t (f a) -> f (t a) surround :: Functor f => (a -> f b) -> t a -> f (t b) class Lone f => Detachable f where type Corep f cotabulate :: (Corep f, a) -> f a coindex :: f a -> (Corep f, a) 连接的几点评论:

  • Traversablecodistribute分别只是surroundsequenceA,除了traverse约束放宽到Applicative(如果始终只有一个值,则Functor是不必要的。)

  • 使用相同的令牌,Applicativecotabulate(或coindexslotseparateunsplitL)可以被视为the shape-and-contents decomposition of traversable functors的一种表现形式(其中,我们不需要内容的列表/向量,因为同样,总是存在一个唯一的值)。

  • 可以想象成对的各种实例可以通过splitL进行翻译。对于Detachable,甚至不需要,因为Comonad就足够了(另请参见附加语中的extractL and duplicateL)。

  • Lone是van Laarhoven镜头(用{em> lens 来说是surround),就像Lens (t a) (t b) a b是van Laarhoven遍历({ {1}}。

最后但并非最不重要的一点,traverse是您的Traversal (t a) (t b) a b的概括。