Haskell 为列表创建新的Ord实例
这是我第一次尝试创建类(如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非常容易。(巧
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非常直观,一旦你有了答案,顺便说一句,下面是