[英]The Monoid type class
I am trying to play around with monoids in Haskell, using this page: https://en.wikibooks.org/wiki/Haskell/Monoids .我正在尝试在 Haskell 中使用幺半群,使用此页面: https://en.wikibooks.org/wiki/Haskell/Monoids 。 I entered the following information in the terminal (after importing
Data.Monoid
):我在终端中输入了以下信息(在导入
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)
However, when I then try Sum 5 <> Sum 6 <> Sum 10
, I receive the following message:但是,当我尝试
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
I don't understand what errors these are, and why Sum 5 <> Sum 6 <> Sum 10
didn't work.我不明白这些是什么错误,以及为什么
Sum 5 <> Sum 6 <> Sum 10
不起作用。
The problem is that you are using your own Sum
type and Monoid
type class with an operator <>
that is not the same function as your version of mappend
.问题是您使用自己的
Sum
类型和Monoid
类型 class 和运算符<>
与您的 mappend 版本不同的mappend
。 If you were to enter this program in a multi-line GHCi prompt:如果您要在多行 GHCi 提示符中输入此程序:
> :{
Prelude| ...paste your program in here...
Prelude| :}
>
and then try this instead:然后试试这个:
> Sum 5 `mappend` Sum 6 `mappend` Sum 7
Sum 5 `mappend` Sum 6 `mappend` Sum 7 :: Num a => Sum a
there would be no error.不会有错误。 If you added a
deriving (Show)
to your Sum
type, you'd even get the answer you're looking for!如果您在
Sum
类型中添加了deriving (Show)
,您甚至会得到您正在寻找的答案!
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}
λ>
The rules for overriding library definitions in GHCi can be a little complicated, so it might be a better idea to put this into a xxx.hs
file and load it into GHCi with :l xxx.hs
for testing.在 GHCi 中覆盖库定义的规则可能有点复杂,因此最好将其放入
xxx.hs
文件并使用:l xxx.hs
将其加载到 GHCi 中进行测试。 If you'd tried to load this program as a xxx.hs
file, you would have gotten much clearer messages about the problem:如果您尝试将此程序作为
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
Then, you could use the special import Prelude
syntax to hide the library definitions you didn't want.然后,您可以使用特殊的
import Prelude
语法来隐藏您不想要的库定义。 The following version works as a self-contained program:以下版本作为独立程序工作:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.