如何在Haskell中正确使用警卫?

时间:2017-03-06 18:33:57

标签: list function haskell

我是Haskell的新手,我正在尝试编写简单的函数让自己习惯于语法,我想编写自己的函数,将某个元素添加到特定索引的列表中。这是我在Atom(我的文本编辑器)中写的:

addElem :: a->[a]->Int->[a]
addElem elem list index
 | index <= 0            = elem:list
 | index < (length list) = a ++ (elem:b) where a = take index list; b = drop index list
 | otherwise             = list

这个想法是,只要索引是Int并且elemlist的元素属于同一类型,它就不会吓到,但是当我尝试加载到ghci我得到“|''的解析错误。”我是否需要约束参数的类型?我正在阅读Learn You A Haskell,但我还没有完全解释缩进的工作原理,所以我的错误也可能就在那里。

1 个答案:

答案 0 :(得分:11)

where块需要在整个函数结束时发生,并在所有情况下共享。您可能打算使用let

addElem :: a -> [a] -> Int -> [a]
addElem elem list index
 | index <= 0            = elem:list
 | index < (length list) = let a = take index list; b = drop index list in a ++ (elem:b)
 | otherwise             = list

另请注意,let可以更简洁地编写为let (a,b) = splitAt index list in ...splitAt也在序曲中。当然,您也可以将where块移动到函数的末尾(Haskell的懒惰使得这很容易理解)。

addElem :: a -> [a] -> Int -> [a]
addElem elem list index
 | index <= 0            = elem:list
 | index < (length list) = a ++ (elem:b)
 | otherwise             = list
 where
   a = take index list
   b = drop index list

就个人而言,我更喜欢这个,因为它表明ab可以在函数的其他地方使用。

2010 Haskell Report的第4.4.3节详细介绍了允许where的位置。