如何在Haskell中结束模式匹配

时间:2018-03-14 13:07:58

标签: haskell recursion

我需要实现一个带有元素elt和列表lst的函数,并返回elt中第一次出现lst的位置。

这是我的答案:

elementPosition :: Eq t => t ->[t] -> Int
elementPosition t [] = 0 
elmentPosition t lst 
    | t == head lst  = 1
    | otherwise      = (elementPosition t (tail lst))+1

但是,如果elt不在lst,我需要返回0.但此代码将返回lst的长度。当第一个模式匹配时,我可以做一些事情来返回0吗?如果没有,我该如何实现这个功能?

4 个答案:

答案 0 :(得分:3)

您必须将递归转换为尾部,以便最终决定在堆栈的顶部,而不是在底部。这样你就需要将当前从列表头部累积的距离作为参数传递(当找到匹配时你需要这个距离但如果没有则可以丢弃它)。像

这样的东西
elementPosition :: Eq t => t ->[t] -> Int
elementPosition pat lst = elementPosition' 1 pat lst where
    elementPosition' _ _ [] = 0
    elementPosition' i pat (h:t) | pat == h = i
                                 | otherwise = elementPosition' (i + 1) pat t

但请注意,标准库已经涵盖了它:

import Data.List

elementPosition :: Eq t => t ->[t] -> Int
elementPosition p l = maybe 0 succ $elemIndex p l

答案 1 :(得分:2)

试试这个:

app.UseMvc(routes =>
   {
       routes.MapRoute( //default
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");

        routes.MapRoute(
            name: "fooid",
            template: "{controller=Home}/{action=Index}/{fooid?}");

        routes.MapSpaFallbackRoute(
            name: "spa-fallback",
            defaults: new { controller = "Home", action = "Index" });
    });

然后elementPosition :: Eq t => Int -> t -> [t] -> Int elementPosition _ _ [] = 0 elementPosition pos key (x:xs) | key == x = pos | otherwise = elementPosition (pos + 1) key xs 会做你想做的事情

答案 2 :(得分:2)

其他答案讨论如何通过添加累加器来实现此目的。但是,我认为如果没有累加器,如何做到这一点也是很有启发性的;诀窍就是检查递归调用的返回值是否为0并保持该值而不是递增值(如果是)。所以:

elementPosition :: Eq t => t -> [t] -> Int
elementPosition t [] = 0
elementPosition t lst
    | t == head lst = 1
    | otherwise = case elementPosition t (tail lst) of
        0 -> 0
        n -> n+1

答案 3 :(得分:1)

另外,使用zip(使列表成为元素及其索引元组的列表)和filter(过滤掉我们要查找的值),我们可以得到这个定义: / p>

elementPosition :: Eq t => t -> [t] -> Int
elementPosition e xs =
  case filter ((== e) . fst) xsIndexed of
    [] -> 0
    (_, i):_ -> i
  where xsIndexed = zip xs [1..]

正如@dfeuer所建议的那样,我们可以在单行中得到这个:

import Data.Maybe

elementPosition :: Eq t => t -> [t] -> Int
elementPosition e = maybe 0 fst . listToMaybe . filter ((== e) . snd) . zip [1..]