2012-01-23 28 views
1

如下我已經定義的自定義類型。Haskell的訪問元組數據的內部列表綜合

這將是很好:

[x | x <- p, d == nm] 
where 
    (_, _, _, _, _, _, d, _) = x 

其中p是原子的列表。

但是,這不起作用,因爲我無法訪問列表理解之外的變量x,也不能想到從列表理解中訪問特定元組值的方法。

有沒有我缺少的元組方法,或者我應該使用不同的數據結構?

我知道我可以編寫一個遞歸函數來解開和檢查列表p中的每個元組,但是我實際上試圖使用這個嵌套在一個已經遞歸的函數中,所以我不想介紹這種複雜性。

回答

9

這工作:

[x | (_, _, _, _, _, _, d, _) <- p, d == nm] 

然而,你應該真的這裏定義自己的數據類型。一個三元組元組是可疑的;一個八元組元組確實是一個非常糟糕的消息。元組很難與數據類型一起使用,並且類型安全性較低(如果用兩個具有相同元素類型的元組表示兩種不同類型的數據,則它們可以互換使用)。以下是我會寫Atom作爲記錄:(該「原子」前綴是爲了避免與其他記錄字段的名稱衝突)

data Point3D = Point3D Double Double Double 

data Atom = Atom 
    { atomRef :: Int 
    , atomPos :: Point3D 
    , atomSymbol :: Word8 
    , atomName :: ByteString 
    , atomSeqNum :: Int 
    , atomAcidAbbrev :: ByteString 
    } deriving (Eq, Show) 

然後,您可以編寫列表理解爲如下:

[x | x <- p, atomSeqNum x == nm] 

作爲獎勵,你的Atom定義成爲自我記錄,和你收穫增加了類型安全的好處。這裏是你如何使用這個定義創建Atom

myAtom = Atom 
    { atomRef = ... 
    , atomPos = ... 
    , ... etc. ... 
    } 

順便說一句,它可能是一個好主意,使某些類型的嚴格的領域,這可以通過將一個感嘆號前完成的該字段的類型;這有助於避免空間泄漏從未評估的thunks建立。例如,由於它沒有多大意義,評估Point3D還沒有評估它的所有組件,我反而定義爲Point3D

data Point3D = Point3D !Double !Double !Double 

這可能會是一個好主意,使Atom所有字段也是嚴格的,雖然也許不是全部;例如,ByteString字段應該保留非嚴格,如果它們是由程序生成的,並不總是被訪問且可能很大。另一方面,如果它們的值是從文件中讀取的,那麼它們應該被嚴格限制。

+0

是的,這是完美的。謝謝。現在,世界看起來非常光明。 –

+0

僅僅因爲它很難合作,或者元組在表現上也很難,是一個「八元組元組」非常糟糕的消息嗎? –

+1

我已經擴大了我的答案,建議您對上面的問題進行鍼對性的提議,因此建議對某些字段進行嚴格處理。以及忘記'-O2',嚴格性不足是最常見的Haskell性能問題之一。 :) – ehird

4

您應該絕對使用不同的結構。不要使用元組,請看records

data Atom = Atom { reference :: Int 
       , position :: (Double, Double, Double) 
       , symbol :: Word8 
       , name :: ByteString 
       , residue :: Int 
       , abbreviation :: ByteString 
       } 

然後你可以做這樣的事情:

a = Atom ... 
a {residue=10} -- this is now a with a residue of 10 
+0

謝謝!我沒有意識到記錄數據結構允許命名單個組件。我錯過了基本的東西,在這裏! –

+1

@kienjakenobi你應該看看[學習你一個Haskell](http://learnyouahaskell.com/)和[其他偉大的資源](http://www.haskell.org/haskellwiki/Learning_Haskell)。 –

+0

謝謝,我已經閱讀了Lean You Haskell的部分內容,而且我甚至還使用過記錄。我根本不知道記錄有一個命名方案。 –