例如我有以下内容,
type something = (Float, Float, Int, Aa, Bb, Cc, Int)
如果我想在他们的第一个元素(Float)中找到最小的something
我该怎么办?我的理由如下,但我无法设法如何实现它
因为我有一个somethings
列表,最简单的方法应该是创建我自己的min
辅助函数,比较2 somethings
并返回两者中最小的一个。然而,它试图以“更简单的方式”让我陷入类型编译错误......
findMin :: something -> something -> somthing
findMin x y = sortBy (compare `on` fst) x y
我不熟悉sortBy
和compare on
,我刚刚在SO中遇到过类似的问题,但我无法使其成功。作为Haskell的初学者,还有另一种方法可以解决这个问题吗?
答案 0 :(得分:6)
如果要根据数据类型的第一个字段进行比较,可以让Haskell为您编写代码:
data Something = Something Float Float Int String Bool Char Int
deriving (Eq, Ord)
deriving
子句指定为Something
类型自动生成的类型类实现。在这里,我们推导出Eq
,它允许我们询问两个Something
是否相等(例如,==
)和Ord
,这允许我们比较两个Something
1}}并知道哪一个是“更大”。
派生Ord
时Haskell的默认行为是从头到尾比较每个字段,因此默认代码将首先比较每个Float
的{{1}},这正是你想要的。
在处理实现Something
的类型后,您可以使用各种内置函数,例如Ord
。这将获取实现minimum :: Ord a => [a] -> a
的任何类型的列表,并返回最小的元素。所以,作为一个例子:
Ord
答案 1 :(得分:5)
首先有一些语法错误。
你可以做两件事。首先,遵循使用访问器函数来获取所需字段的模型(fst
),我们可以为您的类型字段定义标签:
data Something = Something { field_x, field_y :: Float,
field_z :: Int }
然后按field_x
import Data.List
import Data.Function
sortSomethings :: [Something] -> [Something]
sortSomethings = sortBy (compare `on` field_x)
获得最小值与从排序列表中删除头部相同:
minSomethings :: [Something] -> Something
minSomethings = head . sortSomethings
或者,您可以为Ord
类型编写自定义Something
实例,仅使用field_x
,然后定期sort
和minimum
(和其他基于Ord
的函数)将“正常工作”。
答案 2 :(得分:5)
使用自定义data
类型通常是更好的选择,但如果您真的想使用元组,则可以从定义辅助函数comparingFst
开始,该函数根据元组的第一个元素进行比较
import Data.Ord
import Data.List
-- Dummy data types for example purposes. Derive from Show just so
-- that the example can be more easily tested interactively in ghci.
data Aa = Aa deriving Show
data Cc = Cc deriving Show
type Something = (Float, Float, Int, Aa, Cc, Int)
comparingFst :: Something -> Something -> Ordering
comparingFst = comparing fstSomething
where fstSomething (x,_,_,_,_,_) = x
现在您可以使用以下两个元素中的较小元素:
findMin :: Something -> Something -> Something
findMin x y = case comparingFst x y of
LT -> x
_ -> y
或来自元素列表
findMinimum :: [Something] -> Something
findMinimum = minimumBy comparingFst
您还可以使用相同的辅助函数进行排序:
sortSomethings :: [Something] -> [Something]
sortSomethings = sortBy comparingFst
此外,值得一提的是,默认情况下,元组从第一个元素开始按元素进行比较,因此假设Aa
和Bb
类型可以从Ord
派生和Eq
,你不需要任何额外的东西,例如:
import Data.List
data Ab = Ab deriving (Show, Ord, Eq)
data Cc = Cc deriving (Show, Ord, Eq)
type Something = (Float, Float, Int, Ab, Cc, Int)
findMin :: Something -> Something -> Something
findMin x y = min x y
findMinimum :: [Something] -> Something
findMinimum = minimum
sortSomethings :: [Something] -> [Something]
sortSomethings = sort
换句话说,您可以按原样使用标准min
和sort
功能。