2011-04-27 120 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