【发布时间】:2018-05-02 08:36:58
【问题描述】:
GHC Prelude 中列表的默认 monoid 是串联。
[1,2,3] <> [4,5,6] 变为 [1,2,3] ++ [4,5,6] 并因此变为 [1,2,3,4,5,6]
我想编写一个行为如下的 ZipList Monoid 实例:
[
1 <> 4
, 2 <> 5
, 3 <> 6
]
结果是 [5,7,9] 假设我使用的是 sum monoid。
请注意,这类似于zipWith (+)
它的行为可能是这样的:
[
Sum 1 <> Sum 4
, Sum 2 <> Sum 5
, Sum 3 <> Sum 6
]
我需要围绕ZipList 新类型和Sum 新类型创建一个新类型,以便为Monoid、Arbitrary 和EqProp 创建一个实例。
从而避免孤儿实例。
这就是ZipList 和Sum 在Prelude 中的样子:
newtype ZipList a = ZipList { getZipList :: [a] }
newtype Sum a = Sum { getSum :: a }
这就是我的新类型MyZipList 的样子:看起来对吗?
newtype MyZipList a =
MyZipList (ZipList [a])
deriving (Eq, Show)
instance Monoid a => Monoid (MyZipList a) where
mempty = MyZipList (ZipList [])
mappend (MyZipList z) (MyZipList z') =
MyZipList $ liftA2 mappend z z'
instance Arbitrary a => Arbitrary (MyZipList a) where
arbitrary = MyZipList <$> arbitrary
instance Eq a => EqProp (MyZipList a) where
(=-=) = eq
这就是我的 newtypeMySum 的样子:
这看起来对吗?
newtype MySum a =
MySum (Sum a)
deriving (Eq, Show)
instance (Num a, Monoid a) => Monoid (MySum a) where
mempty = MySum mempty
mappend (MySum s) (MySum s') = MySum $ s <> s'
instance Arbitrary a => Arbitrary (MySum a) where
arbitrary = MySum <$> arbitrary
我需要帮助找出我出错的地方。
【问题讨论】:
-
但是
x <> mempty == mempty <> x == x(这是幺半群的属性之一),在你的情况下是mempty <> x == mempty。我认为在ZipList的情况下,mappend应该等于memptys(a类型)的无限列表。 -
为什么要创建一个新的 newtype 而不是为
ZipList a添加一个 Monoid 实例? -
@DominiqueDevriese "我需要创建一个新类型...从而避免孤儿实例。"
-
如果您的目标是让
MySum的行为与Sum完全相同,那么至少看起来是正确的。虽然我不确定你为什么要包装Sum和ZipList,但如果你要重新实现它们的行为——你不妨直接构建MySum和MyZipList。话虽如此,你说你需要帮助,但你实际上并没有说你的问题是什么。您很好地解释了您的实际操作,但您的问题缺少对实际问题的描述。