2011-05-18 70 views
3

作为初学者练习,我已经实现了以下功能找到的第n个元素的列表:Haskell代码是否有效?

elem_at (h:_) 0 = h 
elem_at (_:t) n = elem_at t (n-1) 
elem_at _ _  = error "Index out of bounds" 

但是,如果我叫:elem_at [1,2,3,4] 5,它是否正确,只有在遍历整个列表后才会返回“索引超出范围”,以便最后一行匹配模式_ _和[] 1?更一般地说,如果名单是不会是一个性能问题?可以以某种方式优化这种情况吗?

回答

4

实际上,这正是索引列表的标准方法。您需要在检查负数

elem_at xs n | n < 0 = error "elem_at: negative index" 

而且你可以添加一个特定的比赛为空列表中添加:

elem_at [] _   = error "elem_at: index too large" 

和基础和感性情况:

elem_at (x:_) 0   = x 
elem_at (_:xs) n   = elem_at xs (n-1) 

和你有列表索引的前奏定义,(!!)操作符。

通过工作包装可以产生一个稍微高效的版本,将索引测试浮动到顶层。

+0

谢谢!这就说得通了。但是请等待......数学[] _,从[1,2,3,4]和5开始,我必须使用归纳情形4次,对不对? – Frank 2011-05-18 22:46:49

+0

如果n太大,您会遇到elem_at [] _的基本情况。这很好,因为如果将n与长度进行比较,则最终遍历列表一次以获取长度,然后再次查找该元素。 – 2011-05-18 22:47:02

+0

@你说得对。补充问题:Haskell是否在内部存储列表的长度,以便查询它可能真的很快? – Frank 2011-05-18 22:49:08

2

我相信haskell的实现和遍历任何语言的单链表一样高效。如果数据存储在不同的结构中,则可以在不遍历列表的情况下回答问题。

+0

我的“问题”是我非常喜欢上面的代码,因为它非常简洁。如果我可以写更多的东西,并且在运行时仍然有非常高效的代码,那将是理想的。我已经编写了另一个版本,可以更快速地触发错误(我认为),但它并不优雅。 – Frank 2011-05-18 22:42:41

+0

如果您有一个静态列表,并且您只想快速查找,则可以通过将列表转换为数组来获得效率提升。 http://www.haskell.org/haskellwiki/Modern_array_libraries – 2011-05-18 22:45:37

相关问题