首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Haskell,单体变压器是独一无二的吗?

在Haskell,单体变压器是独一无二的吗?
EN

Stack Overflow用户
提问于 2022-06-03 13:48:52
回答 3查看 235关注 0票数 4

有几个问题(例如,)在Haskell (IO以外)的每个单播中是否都有相应的单台转换器。现在我想提出一个补充问题。是每个单机都有一个变压器(或者没有一个变压器,就像IO那样),还是可以有多个变压器?

一个反例将是两个单台变压器,当应用到身份单端时会产生行为相同的单片,但如果应用到其他单模上,则会产生不同的行为单点。如果答案是一个单一的可以有多个变压器,我想有一个Haskell的例子,这是尽可能简单的。这些并不一定是真正有用的变压器(虽然这会很有趣)。

链接问题中的一些答案似乎表明,一台单机可能有多台变压器。然而,除了范畴的基本定义之外,我不知道更多的范畴理论,所以我不确定它们是否是这个问题的答案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-06-03 19:36:14

标识单元至少有两个单一变压器:标识单变压器和共密度单片变压器

代码语言:javascript
复制
newtype IdentityT m a = IdentityT (m a)
newtype Codensity m a = Codensity (forall r. (a -> m r) -> m r)

实际上,考虑到Codensity Identityforall r. (a -> r) -> ra是同构的。

这些单台变压器完全不同。例如,可以将“括号”定义为Codensity中的一元操作。

代码语言:javascript
复制
bracket :: Monad m => m () -> m () -> Codensity m ()
bracket before after = Codensity (\k -> before *> k () *> after)

然而,将该签名转换到IdentityT并没有多大意义

代码语言:javascript
复制
bracket :: Monad m => m () -> m () -> IdentityT m ()  -- cannot implement the same functionality

其他的例子也可以从延拓/共密度monad的变体中找到,尽管我还没有看到一般的方案。

状态单模对应于状态单端变压器以及CodensityReaderT的组成。

代码语言:javascript
复制
newtype StateT s m a = StateT (s -> m (s, a))
newtype CStateT s m a = CStateT (Codensity (ReaderT s m) a)

列表单片对应至少三个单台变压器,但不包括错误的变压器:

代码语言:javascript
复制
newtype ListT m a = ListT (m (Maybe (a, ListT m a)))  -- list-t
newtype LogicT m a = LogicT (forall r. (a -> m r -> m r) -> m r -> m r)  -- logict
newtype MContT m a = MContT (forall r. Monoid r => (a -> m r) -> m r))

前两个可以分别在包列表-t (也是喉管中的等效形式)和罗克特中找到。

票数 1
EN

Stack Overflow用户

发布于 2022-06-03 18:09:30

这里有一个关于唯一性的反例子的想法。我们知道在一般情况下,单簧管不构成..。但是我们也知道,如果有一个适当的swap操作,您可以编写them1!让我们为可以与自己交换的monads创建一个类。

代码语言:javascript
复制
-- | laws (from [1]):
-- swap . fmap (fmap f) = fmap (fmap f) . swap
-- swap . pure = fmap pure
-- swap . fmap pure = pure
-- fmap join . swap . fmap (join . fmap swap) = join . fmap swap . fmap join . swap
class Monad m => Swap m where
    swap :: m (m a) -> m (m a)

instance Swap Identity where swap = id
instance Swap Maybe where
    swap Nothing = Just Nothing
    swap (Just Nothing) = Nothing
    swap (Just (Just x)) = Just (Just x)

然后,我们可以构建一个单台变压器,它可以自己组成一个单台,如下所示:

代码语言:javascript
复制
newtype Twice m a = Twice (m (m a))

希望pure(<$>)所做的事情应该是显而易见的。我将定义(>>=),而不是定义join,因为我认为它所发生的事情更加明显;(>>=)可以从它派生出来。

代码语言:javascript
复制
instance Swap m => Monad (Twice m) where
    join = id
        . Twice                        -- rewrap newtype
        . fmap join . join . fmap swap -- from [1]
        . runTwice . fmap runTwice     -- unwrap newtype

instance MonadTrans Twice where lift = Twice . pure

我没有检查lift是否对所有Swap实例都遵守了MonadTrans定律,但我确实检查了它们的IdentityMaybe

现在,我们

代码语言:javascript
复制
IdentityT Identity ~= Identity ~= Twice Identity
IdentityT Maybe    ~= Maybe   !~= Twice Maybe

这表明IdentityT并不是生产Identity的唯一单变压器。

由Mark P. Jones和Luc Duponcheel创作的单曲

票数 3
EN

Stack Overflow用户

发布于 2022-10-01 16:54:43

还有另一个例子,一个单一的,有两个不平等的变压器:“选择”单。

代码语言:javascript
复制
 type Sel r a = (a -> r) -> a

这个单子并不为人所知,但有一些报纸提到了它。这是一个参考一些文件的包裹:

https://hackage.haskell.org/package/transformers-0.6.0.4/docs/Control-Monad-Trans-Select.html

该包实现了一个转换器:

代码语言:javascript
复制
type SelT r m a = (a -> m r) -> m a

但是有第二个变压器:

代码语言:javascript
复制
type Sel2T r m a = (m a -> r ) -> m a

证明这台变压器的法律比较困难,但我已经做到了。

第二个转换器的一个优点是它在m中是协变的,因此可以定义hoist函数:

代码语言:javascript
复制
 hoist :: (m a -> n a) -> Sel2T r m a -> Sel2T r n a

第二个变压器是“全功能”,有所有的电梯和“提升机”。第一个转换器功能不全;例如,您不能定义blift :: Sel r a -> SelT r m a。换句话说,不能将Sel中的一元计算嵌入到SelT中,就像不能用连续单元和共密度元嵌入一样。

但是使用Sel2T转换器,所有的电梯都存在,您可以将Sel计算嵌入到Sel2T中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72490608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档