为什么Haskell决定不使用`+`进行字符串(列表)连接?

时间:2018-04-14 08:56:34

标签: haskell

由于我在搜索这个问题时遇到了麻烦,我想我会把它发布在这里。

我只是对它背后的逻辑感兴趣,或者它只是创造者'优先使用++。我的意思是,对于使用+连接两个字符串(或更确切地说是列表)的字符串,使用类型类似乎并不难想象。

编辑:我应该补充一点,在Haskell中必须怀疑其背后的原因,因为+++是在类型类中定义的函数,而在java中则是用于字符串连接的+只是语言语法的一部分,因此仅受创作者偏好/意见的影响。 (到目前为止的答案表明我对自己的怀疑是正确的。)

此外,haskell来自数学背景,深受数学语法的影响,因此可能有更深层次的原因,而不仅仅是偏好/意见。

2 个答案:

答案 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]

很容易看到第一个问题:如果我们希望(+)在列表上工作,我们就必须实施(*)negateabssignumfromInteger也适用于列表。这是假的。

如果我们决定从类型类中分离(+),并为Plussable创建一个新的类型类,可能称为(+),那么将会有太多的类型类跟踪,并且很简单像1 + 2*(2-1)这样的表达式不再是Num a => a类型,它的类型为(Plussable a, Timesable a, Minusable a) => a,依此类推每个操作。这太复杂了。