gpt4 book ai didi

haskell - 为 Reader 实现幺半群

转载 作者:行者123 更新时间:2023-12-05 09:15:52 25 4
gpt4 key购买 nike

我在这里的想法可能很天真,但我认为如果 Reader 的右手值是 Monoid 的实例,那么 Monoid 可以为 Reader 定义...这是我的实现:

instance Monoid a => Monoid (Reader r a) where
mempty = pure mempty
mappend ra rb = (<>) <$> ra <*> rb

然而,这会导致以下错误:

    • Illegal instance declaration for ‘Monoid (Reader r a)’
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use TypeSynonymInstances if you want to disable this.)
• In the instance declaration for ‘Monoid (Reader r a)’
|
413 | instance Monoid a => Monoid (Reader r a) where
| ^^^^^^^^^^^^^^^^^^^

我不确定这个错误的实际含义,以及为什么我无法为 Reader 实现 Monoid,尽管我认为这与 Reader< 有关 是更高等的类型?

最佳答案

有两个问题。第一个是这样的:

type Reader r = ReaderT r Identity

由于历史原因,实例声明中不允许使用类型同义词。这是

where T is not a synonym.

部分错误。幸运的是,我们可以扩展同义词;这会给我们

instance Monoid a => Monoid (ReaderT r Identity a)

但现在我们会发现错误的另一部分,即:

All instance types must be of the form (T t1 ... tn)

具体来说,Identity 不是类型变量,因此不符合这种形式。同样,此限制的存在主要是出于历史原因。您可以通过启用两种语言扩展来取消这两种限制:

{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}

但是,在这种情况下不需要。更好的方法是实际使用实例声明的规定形式,因此:

instance (Applicative f, Monoid m) => Monoid (ReaderT r f m) where
mempty = pure mempty
mappend = liftA2 mappend

这不需要扩展,不仅适用于 Reader,还适用于 ReaderT 转换任何 Applicative 实例。

但是它确实创建了一个孤儿实例;因此你应该考虑编写另一个新类型包装器。

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- or, instead of GeneralizedNewtypeDeriving, write the obvious instances by hand
newtype App f m = App { getApp :: f m } deriving (Functor, Applicative)
instance (Applicative f, Monoid m) => Monoid (App f m) where
mempty = pure mempty
mappend = liftA2 mappend

然后只要 a 是幺半群,您就可以将 App (Reader r) a 用作幺半群。我似乎记得这已经存在于标准库的某个地方,但我再也找不到了......

关于haskell - 为 Reader 实现幺半群,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51640282/

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