初始化记录语法数据类型列表

时间:2011-10-09 11:32:49

标签: haskell

我可以用这样漂亮的方式初始化Int列表:

[2, 4 .. 20]

我只是想知道是否有任何以这种方式初始化我的数据类型列表。像这样的东西,但使用更多的haskell方式:

data SieveElement = SieveElement { index :: Int,
                                   flag ::  Bool 
                                   } deriving (Show)

prepareSieve start end step
             | start > end = []
             | otherwise = [SieveElement start True] ++ (prepareSieve (start + step) end step)

let s = prepareSieve 2 20 2

2 个答案:

答案 0 :(得分:5)

如何使用列表推导:

[SieveElement i True | i <- [2, 4 .. 20]]

答案 1 :(得分:3)

虽然Sjoerd's answer是您的代码的正确方法,但我觉得值得指出的是,良好的列表范围语法可用于Int以上。作为Enum实例的任何数据类型都可以以相同的方式在列表中使用:

  • [a..]被翻译为enumFrom a
  • [a,b..]被翻译为enumFromThen a b
  • [a..c]被翻译为enumFromTo a c
  • [a,b..c]被翻译为enumFromThenTo a b c

但这并不适用于您的示例,因为我不知道有一种很好的方法可以为您的类型声明这样的实例。例如,您似乎想要succ (SieveElement i f) = SieveElement (succ i) f - 忽略该标志 - 但是,您不清楚如何以这样的方式实现toEnum :: Int -> afromEnum :: a -> Int,以便您可以构建所有SieveElements 1}},同时包含TrueFalse个标记。


修改:正如评论中指出的newacct一样,toEnum无需涵盖整个范围:考虑FloatDoubletoEnum只生成整数。另一个例子是fromEnum (pi :: Double) == (3 :: Int)。因此,您可以定义Enum的实例。但是,天真地这样做是行不通的:

data SieveElement = SieveElement { index :: Int
                                 , flag  :: Bool }
                  deriving (Show)

-- Warning: broken!
instance Enum SieveElement where
  succ (SieveElement i f) = SieveElement (succ i) f
  pred (SieveElement i f) = SieveElement (pred i) f
  toEnum i = SieveElement i False -- or True
  fromEnum (SieveElement i _) = i

使用enumFrom*系列方法有一些不良行为:

*Main> [SieveElement 2 True .. SieveElement 3 True]
[SieveElement {index = 2, flag = False},SieveElement {index = 3, flag = False}]

不幸的是,由于the default enumFrom* implementationsfromEnum / toEnum,因此您将失去旗帜。当然,你可以重新实现这些,但是我不确定像[SieveElement 2 True, SieveElement 4 False .. SieveElement 10 True]这样的东西你想要什么样的语义。总的来说,这些是更多,更好的原因,我认为Sjoerd's answer绝对是正确的方法。