由于我在搜索这个问题时遇到了麻烦,我想我会把它发布在这里。
我只是对它背后的逻辑感兴趣,或者它只是创造者'优先使用++
。我的意思是,对于使用+
连接两个字符串(或更确切地说是列表)的字符串,使用类型类似乎并不难想象。
编辑:我应该补充一点,在Haskell中必须怀疑其背后的原因,因为+
和++
是在类型类中定义的函数,而在java中则是用于字符串连接的+
只是语言语法的一部分,因此仅受创作者偏好/意见的影响。 (到目前为止的答案表明我对自己的怀疑是正确的。)
此外,haskell来自数学背景,深受数学语法的影响,因此可能有更深层次的原因,而不仅仅是偏好/意见。
答案 0 :(得分:16)
用于连接两个字符串的字符串的类型类
这样的类型类存在,虽然运算符不是+
,而是<>
:
Prelude> :m +Data.Monoid
Prelude Data.Monoid> "foo" <> "bar"
"foobar"
虽然++
连接了列表,但<>
运算符更通用,因为它结合了给定Monoid
实例的任意两个值。
正如其他人所指出的那样,+
保留给Num
个实例。为什么Monoid
二元运算符不是+
?因为加法只是无限多的幺半群之一;乘法是另一个:
Prelude Data.Monoid> Sum 2 <> Sum 3
Sum {getSum = 5}
Prelude Data.Monoid> Product 2 <> Product 3
Product {getProduct = 6}
选择类似<>
之类的''monoidal运算符是首选,因为它几乎没有语义包袱。
答案 1 :(得分:3)
长话短说,这会引起类型麻烦。
(+)
是Num
类型类的一部分:
class Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
x - y = x + negate y
negate x = 0 - x
(++) :: [a] -> [a] -> [a]
。
很容易看到第一个问题:如果我们希望(+)
在列表上工作,我们就必须实施(*)
,negate
,abs
,signum
和fromInteger
也适用于列表。这是假的。
如果我们决定从类型类中分离(+)
,并为Plussable
创建一个新的类型类,可能称为(+)
,那么将会有太多的类型类跟踪,并且很简单像1 + 2*(2-1)
这样的表达式不再是Num a => a
类型,它的类型为(Plussable a, Timesable a, Minusable a) => a
,依此类推每个操作。这太复杂了。