2011-04-27 137 views
6

例如,我有以下的,排序抽象数据类型在Haskell

type something = (Float, Float, Int, Aa, Bb, Cc, Int) 

如果我希望找到基地最小something他们的第一个元素(浮动)我怎么能这样做呢?在路上我已经推断它是下面的,但我不能设法figureout如何实现它

因为我有somethings最简单的方法应该是创建一个比较2 somethings我自己min辅助函数列表,并返回最小的两个。但是它正试图做“更简单的方式”让我坚持类型编译错误......

findMin :: something -> something -> somthing 
findMin x y = sortBy (compare `on` fst) x y 

我不熟悉sortBycompare on,我只是碰到了类似的问题来到这里SO但我无法做到这一点。作为Haskell的初学者,是否有另一种方法来解决这个问题?

+1

“fst”和“snd”仅适用于具有两个元素的元组。对于任何事情,你可能比其他人建议的“数据某事= ...”更好。 – 2011-04-28 07:13:55

回答

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

另外,值得一提的是,默认情况下,元组从第一个元素开始进行元素比较,因此假设您的AaBb类型可以从OrdEq派生,则不需要任何额外的东西,即示例变为:

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

换句话说,你可以使用标准的minsort功能原样。

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) 

获得在mimimum是一样的以头部断排序列表:

minSomethings :: [Something] -> Something 
minSomethings = head . sortSomethings 

或者,您也可以编写自定义Ord斯塔只有使用field_x,然后是常规sortminimum(以及其他Ord的函数)比较值的Something类型才会“正常工作”。

+0

此外,比较''比较' – 2011-04-27 23:39:58

6

如果您想根据数据类型的第一个字段进行比较,就可以让哈斯克尔为你写的代码:哪种类型的类实现都为Something自动生成

data Something = Something Float Float Int String Bool Char Int 
       deriving (Eq, Ord) 

deriving子句指定类型。在这里,我们导出Eq,它允许我们询问两个Something是否相等(例如,与==)和Ord,这允许我们比较两个Something并知道哪一个是“更大”。

Haskell的默认行为推导Ord时是每场从第一比较持续,所以默认代码将通过比较每个Something的第一Float,这正是你想要的开始。

处理完Ord的类型后,可以使用各种内置函数,如minimum :: Ord a => [a] -> a。这需要实现Ord的任何类型的列表,并返回最小的元素。所以,作为一个例子:

st1 = Something 3.14 2.72 7 "hello" False 'λ' 42 
st2 = Something 3.15 2.72 7 "hello" False 'λ' 42 

smallest = minimum [st1,st2] 
+2

+1为新手友好简单 – 2011-04-28 03:55:52