Initialize the List of Record Syntax Data Type
I can initialize the list of Int such beautiful way:
[2, 4 .. 20]
And I 开发者_运维技巧am just wondering if there is any to initialize the list of my datatype in such manner. Something like this, but using more haskell way:
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
How about using list comprehensions:
[SieveElement i True | i <- [2, 4 .. 20]]
While Sjoerd's answer is the right way to go for your code, I felt it was worth pointing out that the nice list range syntax is available for more than just Int
s. Any data type which is an instance of Enum
can be used in lists in the same way:
[a..]
is translated asenumFrom a
,[a,b..]
is translated asenumFromThen a b
,[a..c]
is translated asenumFromTo a c
, and[a,b..c]
is translated asenumFromThenTo a b c
.
This doesn't really work for your example, though, since I don't know that there's a good way to declare such an instance for your type. For instance, it seems that you want succ (SieveElement i f) = SieveElement (succ i) f
—ignoring the flag—but then it's not clear how you implement toEnum :: Int -> a
and fromEnum :: a -> Int
in such a way that you can construct all of the SieveElements
, with both True
and False
flags.
Edit: As newacct pointed out in the comments, there's no need for toEnum
to cover the entire range: consider Float
and Double
, for which toEnum
produces only whole numbers. As another example, fromEnum (pi :: Double) == (3 :: Int)
. So you could define an instance of Enum
. However, doing this naïvely won't work:
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
This has some bad behavior with the enumFrom*
family of methods:
*Main> [SieveElement 2 True .. SieveElement 3 True]
[SieveElement {index = 2, flag = False},SieveElement {index = 3, flag = False}]
Unfortunately, since the default enumFrom*
implementations are in terms of fromEnum
/toEnum
, you'll lose your flag. You could reimplement these, of course, but I'm not sure what semantics you would want for something like [SieveElement 2 True, SieveElement 4 False .. SieveElement 10 True]
. In general, these are some more, better, reasons why I think Sjoerd's answer is absolutely the right way to go.
精彩评论