haskell - Monoid 类型类
问题描述
我正在尝试使用此页面在 Haskell 中使用幺半群:https ://en.wikibooks.org/wiki/Haskell/Monoids 。我在终端中输入了以下信息(导入后Data.Monoid
):
class Monoid a where
mempty :: a
mappend :: a -> a -> a
mconcat :: [a] -> a
mconcat = foldr mappend memptyhere
newtype Sum a = Sum { getSum :: a }
instance Num a => Monoid (Sum a) where
mempty = Sum 0
Sum x `mappend` Sum y = Sum (x + y)
但是,当我尝试时Sum 5 <> Sum 6 <> Sum 10
,我收到以下消息:
<interactive>:115:1: error:
• Non type-variable argument in the constraint: Semigroup (Sum a)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Semigroup (Sum a), Num a) => Sum a
我不明白这些是什么错误,以及为什么Sum 5 <> Sum 6 <> Sum 10
不起作用。
解决方案
问题是您使用自己的Sum
类型和Monoid
类型类,其运算符<>
与您的mappend
. 如果您要在多行 GHCi 提示符中输入此程序:
> :{
Prelude| ...paste your program in here...
Prelude| :}
>
然后试试这个:
> Sum 5 `mappend` Sum 6 `mappend` Sum 7
Sum 5 `mappend` Sum 6 `mappend` Sum 7 :: Num a => Sum a
不会有错误。如果你deriving (Show)
在你的Sum
类型中添加了一个,你甚至会得到你正在寻找的答案!
Ok, modules loaded: none.
λ> :{
Prelude| class Monoid a where
Prelude| mempty :: a
Prelude| mappend :: a -> a -> a
Prelude| mconcat :: [a] -> a
Prelude| mconcat = foldr mappend mempty
Prelude| newtype Sum a = Sum { getSum :: a } deriving (Show)
Prelude| instance Num a => Monoid (Sum a) where
Prelude| mempty = Sum 0
Prelude| Sum x `mappend` Sum y = Sum (x + y)
Prelude| :}
λ> Sum 5 `mappend` Sum 6 `mappend` Sum 7
Sum {getSum = 18}
λ>
在 GHCi 中覆盖库定义的规则可能有点复杂,因此将其放入xxx.hs
文件中并将其加载到 GHCi 中:l xxx.hs
进行测试可能是一个更好的主意。如果您尝试将此程序作为xxx.hs
文件加载,您会得到关于该问题的更清晰的消息:
MonoidExample2.hs:7:19-24: error:
Ambiguous occurrence ‘Monoid’
It could refer to
either ‘Prelude.Monoid’,
imported from ‘Prelude’ at MonoidExample2.hs:1:1
(and originally defined in ‘GHC.Base’)
or ‘Main.Monoid’, defined at MonoidExample2.hs:1:1
然后,您可以使用特殊import Prelude
语法来隐藏您不想要的库定义。以下版本作为独立程序工作:
import Prelude hiding (Monoid, mempty, mappend, mconcat, (<>))
class Monoid a where
mempty :: a
mappend :: a -> a -> a
mconcat :: [a] -> a
mconcat = foldr mappend mempty
newtype Sum a = Sum { getSum :: a } deriving (Show)
instance Num a => Monoid (Sum a) where
mempty = Sum 0
Sum x `mappend` Sum y = Sum (x + y)
(<>) :: Monoid a => a -> a -> a
(<>) = mappend
main :: IO ()
main = print $ Sum 5 <> Sum 6 <> Sum 10
推荐阅读
- web2py - 如何使用数据库 slug 字段来显示相应的博客条目和 URL
- css - 'auto' css 属性的 Angular 组件 jenkins 构建问题
- c++ - 如何使用函数作为 C++ 中类的初始化程序
- android - Android Realm 查询反向关系
- time - 如何将美元金额除以时间戳
- python - Discord 机器人如何处理来自多个服务器的事件
- python - 如何获取更平衡的样本数据 Python
- php - 如何执行 2 个条件查询并将数据检索到单个表中
- python - 如何用没有停止号的生成器编写斐波那契
- python - Python 快速更改 8KK 行文件中的 300K 行