我可以用这样漂亮的方式初始化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
答案 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 -> a
和fromEnum :: a -> Int
,以便您可以构建所有SieveElements
1}},同时包含True
和False
个标记。
修改:正如评论中指出的newacct一样,toEnum
无需涵盖整个范围:考虑Float
和Double
, toEnum
只生成整数。另一个例子是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*
implementations是fromEnum
/ toEnum
,因此您将失去旗帜。当然,你可以重新实现这些,但是我不确定像[SieveElement 2 True, SieveElement 4 False .. SieveElement 10 True]
这样的东西你想要什么样的语义。总的来说,这些是更多,更好的原因,我认为Sjoerd's answer绝对是正确的方法。