[英]ZipList Monoid haskell
GHC Prelude 中列表的默认幺半群是串联。
[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]
假设我使用的是和幺半群。 请注意,这类似于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
这就是我的MySum
样子:这看起来对吗?
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
我需要帮助找出我哪里出错了。
首先请注意ZipList
的Applicative
实例已经具有您想要的 zippy 行为。
ghci> liftA2 (<>) (Sum <$> ZipList [1,2,3]) (Sum <$> ZipList [4,5,6]) :: ZipList Int
ZipList [Sum 5, Sum 7, Sum 9]
然后利用这样一个事实,即任何Applicative
通过幺半群函子本身提升其内容的幺半群行为,从而产生一个Monoid
半群。 计划是从我上面写的表达式中抽象出liftA2 (<>)
模式。
newtype Ap f a = Ap { getAp :: f a }
instance (Applicative f, Monoid a) => Monoid (Ap f a) where
mempty = Ap $ pure mempty
Ap xs `mappend` Ap ys = Ap $ liftA2 mappend xs ys
(据我所知, base
缺少这个newtype
,这对我来说似乎是一个疏忽,尽管可能有一个很好的理由。事实上,我认为ZipList
应该有一个开箱即用的Monoid
实例,但是,唉,它没有。)
你想要的Monoid
就是Ap ZipList (Sum Int)
。 这相当于你手工编写的MyZipList
Monoid
(除了你的mempty
的错误 - 它应该是MyZipList $ ZipList $ repeat mempty
),但是用像这样的可重用newtype
s 组成它不是特别的,需要更少的样板.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.