Haskell 在列表中查找元素的索引

Haskell 在列表中查找元素的索引,haskell,indexof,Haskell,Indexof,我是Haskell的初学者,我的练习程序一直有问题。对于这个特殊的元素,我想在列表中查找元素的索引(第一个元素位于0)。 如果给定的元素没有出现在列表中,则程序返回-1 这是我的密码: indexOf :: (Eq a) => a -> [a] -> Int indexOf n [] = (-1) indexOf n (x:xs) | n == x = length(xs) | otherwise = n `indexOf` xs 我在C和Java方面都

我是Haskell的初学者,我的练习程序一直有问题。对于这个特殊的元素,我想在列表中查找元素的索引(第一个元素位于0)。 如果给定的元素没有出现在列表中,则程序返回-1

这是我的密码:

indexOf :: (Eq a) => a -> [a] -> Int
indexOf n [] = (-1)
indexOf n (x:xs)
    | n == x    = length(xs)
    | otherwise = n `indexOf` xs
我在C和Java方面都有经验,所以我的直觉是每次浏览列表时都会得到一个递增计数器,但是,我一直提醒自己Haskell不是这样工作的。 我知道我的代码在每次遍历时都会移动列表的开头,当我执行“length(xs)”时,它只是在查找列表其余部分的长度。
很明显,我在这里很困惑。有人能给我提供一些关于如何使这段代码工作的建议吗?

我解决这段代码的方法是创建另一个递归函数,使用相同的信号加上额外的
Int
参数作为累加器:

indexOf :: (Eq a) => a -> [a] -> Int
indexOf n xs = go 0 n xs
    where
        go i n [] = (-1)
        go i n (x:xs)
             | n == x    = i
             | otherwise = go (i+1) n xs
您还可以在再次返回时修改返回值,而不是计数器(沿列表向下递增):

indexOf :: (Eq a) => a -> [a] -> Int
indexOf n [] = -1
indexOf n (x:xs)
    | n == x    = 0
    | otherwise = case n `indexOf` xs of
        -1 -> -1
        i  -> i + 1

在Haskell中,通常使用
或者a
返回值
a
,但并非所有输入本身都有效。对于无效输入,我们返回
Nothing
,对于有效输入,我们返回
Just x
,结果为
x

因此,我们可以实现
indexOf
,将空列表映射到
Nothing
。如果列表中的第一个项目与我们要查找的项目相同,我们只返回
0
。如果第一个项目不等于我们要查找的项目,我们将在列表的尾部递归,并增加
中包装的值,只要有这样的值:

indexOf :: Eq a => a -> [a] -> Maybe Int
indexOf y = go
    where go [] = Nothing
          go (x:xs) | x == y = Just 0
                    | otherwise = (1+) <$> go xs
indexOf::Eq a=>a->[a]->可能是Int
y=go的索引
去哪儿
go(x:xs)| x==y=0

|否则=(1+)go xs
此函数已经存在于库()中,但我们还是实现它吧

给定
xs=[x0,x1,…]
,我们有
zip xs[0..]=[(x0,0),(x1,1),…]
。然后,我们可以在后一个列表中搜索满足谓词
\(x,\)->x==n
的对

import Data.List

indexOf :: (Eq a) => a -> [a] -> Maybe Int
indexOf n xs = fmap snd . find (\(x,_) -> x==n) $ zip xs [0..]
上面,
zip
添加索引,
find
将在成功时返回
Just(n,index)
,而
fmap snd
将其转换为
Just index

请注意,我们更喜欢返回
Nothing
而不是
-1
,这在Haskell中不是惯用的,我们更喜欢使用
或者

最后,请注意,上面的代码并不是低效的:由于懒惰,
zip
只会将索引添加到
find
所需的那些元素,因此它不会扫描整个列表,除非找不到所需的元素


作为练习,您可能需要编写
fmap snd。使用显式递归查找(\(x,\)->x==n)

对于非total函数,通常返回
Maybe
,因此
Maybe Int
,如果未找到元素,则返回
Nothing
,或者
在索引
i
上找到一个项目时,只需i
。注意,我们可以省略
go
中的
n
参数。