Haskell 为列表创建新的Ord实例

Haskell 为列表创建新的Ord实例,haskell,typeclass,instances,Haskell,Typeclass,Instances,这是我第一次尝试创建类(如Ord)的自定义实例 我定义了一个新的数据结构来表示列表: data List a = Empty | Cons a (List a) deriving (Show, Eq) 现在我想为List定义一个新的Ord实例,这样List a首先,它不会像普通的List实例那样工作。普通实例仅依赖于列表中的项目本身是可排序的;您的提案取决于它们的编号(例如在Num类中),因此范围更窄 必须定义一个新的sum函数。幸运的是,作为一个简单的递归函数编写sum非常容易。(巧

这是我第一次尝试创建类(如Ord)的自定义实例

我定义了一个新的数据结构来表示列表:

data List a = Empty | Cons a (List a)
    deriving (Show, Eq)

现在我想为List定义一个新的Ord实例,这样List a首先,它不会像普通的List实例那样工作。普通实例仅依赖于列表中的项目本身是可排序的;您的提案取决于它们的编号(例如在
Num
类中),因此范围更窄

必须定义一个新的
sum
函数。幸运的是,作为一个简单的递归函数编写
sum
非常容易。(巧合的是,您可以调用函数
sum'
,该函数的发音为“sum prime”,按照惯例,它与
sum
非常相似)

此外,实例必须依赖于
Num
类以及
Ord

一旦有了一个新的
sum
函数,您就可以定义一个如下的实例:

instance (Ord n, Num n) => Ord (List n) where compare = ... 
  -- The definition uses sum'
该实例语句可以理解为,对于所有类型的
n
,如果
n
Ord
Num
中,则
列表n
Ord
中,比较如下所示。语法非常类似于数学,其中
=>
是隐含的。希望这能使记住语法更容易

您必须对
compare
给出合理的定义。作为参考,
compare a b
的工作原理如下:如果
a
它返回
LT
,如果
a=b
它返回
EQ
,如果
a>b
它返回
GT


这是一个易于实现的函数,因此我将把它作为练习留给读者。(我一直想说:P)。

稍微概括一下@Tikhon的方法,你也可以使用

Monoid
而不是
Num
作为约束,在这里你已经有了一个预定义的带有
mconcat
的“和”(当然,你仍然需要
Ord
)。这将为您提供更多的类型,而不仅仅是数字(例如,
List(List a)
,您现在可以轻松地递归定义)

另一方面,如果您确实希望使用
Num
作为幺半群,则必须决定每次使用
Sum
乘积
。可以说,必须明确地写出来可以减少短小性和可读性,但这是一种设计选择,取决于您最终想要达到的通用性程度。

那么

newtype List a = List [a]
如果要为给定类型引入新的“不兼容”类型类实例(例如,请参见
ZipList
或几个幺半群,如
Sum
Product
),这是非常常见的

现在,您可以轻松地重用列表的实例,并且还可以使用
sum

关于

data List a = Empty | Cons a (List a)
                deriving (Show, Eq)


instance (Ord a, Num a, Eq a) => Ord (List a) where

      -- 2 empty lists

      Empty <= Empty            =   True

      -- 1 empty list and 1 non-empty list

      Cons a b <= Empty         =   False
      Empty <= Cons a b         =   True

      -- 2 non-empty lists

      Cons a b <= Cons c d      =   sumList (Cons a b) <= sumList (Cons c d) 


-- sum all numbers in list

sumList         ::      (Num a) => List a -> a

sumList Empty               =       0
sumList (Cons n rest)       =       n + sumList rest
数据列表a=空| Cons a(列表a)
推导(显示,等式)
实例(Ord a、Num a、Eq a)=>Ord(列表a),其中
--2个空列表

空的。。或者前奏曲中的和函数的另一个解

data List a = Empty | Cons a (List a)
                deriving (Show, Eq)


instance (Ord a, Num a, Eq a) => Ord (List a) where

      -- 2 empty lists

      Empty <= Empty            =   True

      -- 1 empty list and 1 non-empty list

      Cons a b <= Empty         =   False
      Empty <= Cons a b         =   True

      -- 2 non-empty lists

      Cons a b <= Cons c d      =   sum (listToList (Cons a b)) 
                                              <= sum (listToList (Cons c d)) 


-- convert new List to old one

listToList      ::      (Num a) => List a -> [a]

listToList Empty                =       []
listToList (Cons a rest)        =       [a] ++ listToList rest
数据列表a=空| Cons a(列表a)
推导(显示,等式)
实例(Ord a、Num a、Eq a)=>Ord(列表a),其中
--2个空列表

空的很好的答案,如果我能。。。Haskell非常直观,一旦你有了答案,顺便说一句,下面是