【问题标题】:How to add two lists like matlab in Haskell?如何在 Haskell 中添加两个类似 matlab 的列表?
【发布时间】:2016-04-07 17:17:38
【问题描述】:

我想知道是否可以编写一个 Haskell 加法运算符来处理两个数字、两个数字列表、两个数字矩阵……等等。也就是说,是否可以定义一个<+> 以使以下所有工作都有效?:

1 <+> 2 = 3
[1] <+> [2] = [3]
[[1]] <+> [[2]] = [[3]]
...

我知道就像What is an idiomatic way to add lists in Haskell? 一样,我们可以为a+,为zipWith (+)[a][[a]] 可能是 zipWith (zipWith (+)),沿着同一条线,依此类推……

但它可以使用一个运算符(就像 Matlab 一样)使用类型类或 Haskell 的其他功能来完成吗?

我知道这是合成糖,但如果可能的话它会很甜。

-- 更新--

我发现使用(Num a) 可能会出现问题,正如@DanielWagner 的回答中所解释的那样,对于基本情况,最好为Integer, Double 等单独定义它。

为了记录,我只是按照建议尝试了:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class Additive a where (<+>) :: a -> a -> a
instance Num a => Additive a where (<+>) = (+)
instance Additive a => Additive [a] where (<+>) = zipWith (<+>)

或者

{-# LANGUAGE DefaultSignatures #-}
class Additive a where
    (<+>) :: a -> a -> a
    default (<+>) :: Num a => a -> a -> a
    (<+>) = (+)

在任何一种情况下,加载.hs 文件或评估[[1,2]] &lt;+&gt; [[3,4]] 时都会出错。

【问题讨论】:

  • 好吧,你可以编写一个类似Monoid 的类,但有不同的实例。
  • 为了让这个有趣,您需要提供更详尽的示例。你想要[1,2] &lt;+&gt; [3,4] 给什么? [[1,2],[3,4]] &lt;+&gt; [[5,6],[7,8]] 呢? [1,2,3,4] &lt;+&gt; [] 呢?有很多边缘情况需要考虑。
  • Matlab/Octave 在最后一个例子中会给出尺寸不匹配错误,否则它是一个X(i,j) + Y(i,j)
  • 即使有可能,这也是个坏主意。如果你问我,Matlab 实际上已经很好地证明了这一点......
  • @leftaroundabout 我认为这对 Matlab 来说是个坏主意,因为尺寸被任意折叠以允许例如1 + [2]。这里不是这样吗?

标签: matlab haskell


【解决方案1】:

是的,有可能:

class Additive a where (<+>) :: a -> a -> a
instance Additive Integer where (<+>) = (+)
instance Additive a => Additive [a] where (<+>) = zipWith (<+>)

你在 ghci 中的三个测试用例:

*Main> 1 <+> 2
3
*Main> [1] <+> [2]
[3]
*Main> [[1]] <+> [[2]]
[[3]]

如果你想要很多 (&lt;+&gt;) = (+) 的实例,你可以使用 DefaultSignatures 将其设为默认实现:

{-# LANGUAGE DefaultSignatures #-}
class Additive a where
    (<+>) :: a -> a -> a
    default (<+>) :: Num a => a -> a -> a
    (<+>) = (+)

优点是某些实例可以很短,例如

instance Additive Integer
instance Additive Int
instance Additive Double
instance Additive Float

无需任何额外的方法定义即可按预期工作。

【讨论】:

  • Num替换Integer的任何优雅方式?
  • 当然:instance Num a =&gt; Additive a where (&lt;+&gt;) = (+)
  • @ReinHenrichs 仅适用于 FlexibleInstances 启用对吗?
  • @AlekseyIzmailov 是的,但FlexibleInstances 肯定是 Haskell 常用 GHC 方言的一部分。
  • @tinlyx 通常,您不能以Num a 作为基本情况。而是为您关心的每种类型创建Additive 的实例——IntDouble 等等。 (想想如果我写instance Num a =&gt; Num [a] where ...会发生什么!)
猜你喜欢
  • 1970-01-01
  • 2020-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-21
相关资源
最近更新 更多