Xan*_*unn 1 haskell types tuples
我已经定义了一个自定义类型如下:
-- Atom reference number, x coordinate, y coordinate, z coordinate, element symbol,
-- atom name, residue sequence number, amino acid abbreviation
type Atom = (Int, Double, Double, Double, Word8, ByteString, Int, ByteString)
Run Code Online (Sandbox Code Playgroud)
我想收集所有具有一定残留序列号nm的原子.
这样会很好:
[x | x <- p, d == nm]
where
(_, _, _, _, _, _, d, _) = x
Run Code Online (Sandbox Code Playgroud)
其中p是原子列表.
但是,这不起作用,因为我不能在列表推导之外访问变量x,也不能想到从列表推导中访问特定元组值的方法.
是否存在我缺少的元组方法,或者我应该使用不同的数据结构?
我知道我可以编写一个递归函数来解包并检查列表p中的每个元组,但我实际上是试图在已经递归的函数中使用这个嵌套,所以我宁愿不需要引入那种复杂性.
这有效:
[x | (_, _, _, _, _, _, d, _) <- p, d == nm]
Run Code Online (Sandbox Code Playgroud)
然而,你应该真正在这里定义自己的数据类型.一个三元素的元组是可疑的; 一个八元素的元组确实是个坏消息.与数据类型相比,元组难以使用且类型安全性较低(如果使用具有相同元素类型的两个元组表示两种不同类型的数据,则它们可以互换使用).这是我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)
Run Code Online (Sandbox Code Playgroud)
("atom"前缀是为了避免与其他记录中的字段名称发生冲突.)
然后,您可以按如下方式编写列表推导:
[x | x <- p, atomSeqNum x == nm]
Run Code Online (Sandbox Code Playgroud)
作为奖励,您的定义将Atom成为自我记录,并且您可以获得增加类型安全性的好处.以下是Atom使用此定义创建的方法:
myAtom = Atom
{ atomRef = ...
, atomPos = ...
, ... etc. ...
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,将这些类型的某些字段设置为严格可能是个好主意,这可以通过在字段类型之前加上感叹号来完成; 这有助于避免来自未评估的thunks积累的空间泄漏.例如,因为在不Point3D评估其所有组件的情况下评估a 没有多大意义,我将其定义Point3D为:
data Point3D = Point3D !Double !Double !Double
Run Code Online (Sandbox Code Playgroud)
Atom尽管也许并非所有领域都是严格的所有领域,但这可能是一个好主意.例如,如果ByteString字段是由程序生成的,则字段应保持非严格,不总是访问且可能很大.另一方面,如果从文件中读取它们的值,那么它们应该是严格的.
| 归档时间: |
|
| 查看次数: |
1325 次 |
| 最近记录: |