初始化记录语法数据类型列表
我可以用这种漂亮的方式初始化 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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用列表推导式如何:
How about using list comprehensions:
虽然Sjoerd的答案是正确的方法去寻找你的代码,我觉得值得指出的是,好的列表范围语法不仅仅适用于
Int
。作为 实例的任何数据类型Enum
可以以相同的方式在列表中使用:[a..]
被翻译为enumFrom a
,[a,b..]
被翻译为enumFromThen a b
,[a..c]
被翻译为enumFromTo a c,并且
[a,b..c]
被翻译为enumFromThenTo ab c
。不过,这对于您的示例并没有真正起作用,因为我不知道有什么好方法可以为您的类型声明这样的实例。例如,您似乎想要 succ (SieveElement if) = SieveElement (succ i) f(忽略该标志),但不清楚如何实现 toEnum :: Int -> a 和
fromEnum :: a -> Int
以这样的方式,您可以构造所有SieveElements
,同时具有True
和False
标志。编辑:正如 newacct 在评论中指出的那样,不需要
toEnum
覆盖整个范围:考虑Float
和Double< /code>,其中
toEnum
仅生成整数。再举一个例子,fromEnum (pi::Double) == (3::Int)
。因此,您可以定义Enum
的实例。然而,天真地这样做是行不通的:这对
enumFrom*
系列方法有一些不好的行为:不幸的是,因为 默认
enumFrom*
实现fromEnum
/toEnum
,你将失去你的标志。当然,您可以重新实现这些,但我不确定您想要什么语义,例如[SieveElement 2 True, SieveElement 4 False .. SieveElement 10 True]
。总的来说,这些是我认为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 ofEnum
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 implementtoEnum :: Int -> a
andfromEnum :: a -> Int
in such a way that you can construct all of theSieveElements
, with bothTrue
andFalse
flags.Edit: As newacct pointed out in the comments, there's no need for
toEnum
to cover the entire range: considerFloat
andDouble
, for whichtoEnum
produces only whole numbers. As another example,fromEnum (pi :: Double) == (3 :: Int)
. So you could define an instance ofEnum
. However, doing this naïvely won't work:This has some bad behavior with the
enumFrom*
family of methods:Unfortunately, since the default
enumFrom*
implementations are in terms offromEnum
/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.