此仿函数标记类类型的名称是什么?

问题描述 投票:4回答:1

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

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并不是很有帮助。

所以我在这里,寻找一个名字,甚至是一些图书馆,看看我还能用这个东西做什么。

haskell typeclass functor
1个回答
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升级为完全逆,从而使我们在f a和[C0之间具有同构]。

这些功能在生态系统中至少存在一处:(f (), a)

the adjunctions package

Hask / Hask左伴随是同构的对函子,与Hask / Hask右伴随是splitL :: Adjunction f u => f a -> (a, f ()) unsplitL :: Functor f => a -> f () -> f a 的同义,即同构对函子。从某种意义上说,Representable是合理的,尽管adjunctions并没有为我们提供Representabledfeuer's suspicion的左伴同伴。这是它们的草图,其中包含虚构的名称:

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) Traversable分别只是codistributesurround,除了sequenceA约束放宽到traverse(如果始终只有一个值,则不需要Applicative) 。

  • 通过相同的记号,FunctorApplicative(或cotabulatecoindexslotseparate)可以看作是unsplitL的体现(我们需要内容没有列表/向量,因为同样总是总有一个值)。

  • 对的各种实例可以通过splitL进行翻译。对于the shape-and-contents decomposition of traversable functors,甚至不需要,因为Detachable就足够了(另请参见adjunctionsComonad)。

  • [Lone是van Laarhoven镜头(用[[lens来说是extractL and duplicateL),就像extractL是van Laarhoven遍历(duplicateL)。

最后但并非最不重要的是,surround是您的Lens (t a) (t b) a b的概括。
© www.soinside.com 2019 - 2024. All rights reserved.