元素在List中的位置

时间:2015-12-13 15:47:57

标签: list elm

我正在尝试获取列表中元素的索引给定其Id。这就是我所拥有的:

type alias Id = Int  

posInList : Id -> List (Id, ItemModel) -> Int
posInList id list =
  if List.isEmpty list then 
      -1
  else 
    if (List.head list).fst == id then
      0
    else 
      if posInList id (List.tail list) == -1 then
        -1
      else
        posInList id (List.tail list) + 1

我从方案代码here得到了这个问题(以7票回答)。

当我编译代码时,我得到两个错误:

type-mismatch enter image description here

我该如何解决这个问题?或者是否有更简单的解决方案?

更新:尝试使用Maybe

posInList : Id -> Maybe List (Id, ItemModel) -> Int
posInList id list =
  case list of
    Nothing -> -1
    Just a -> 
      case (List.head a) of
        Just b -> 
          if b.fst == id then 
            0
          else
            case (List.tail a) of
              Nothing -> -1
              Just c -> (posInList id (Just c)) + 1
        Nothing -> -1

我认为我很接近,但我无法解决此错误:

just-c

Just c的类型为Maybe List,但哪里与Maybe冲突? 我想类型注释,所以我添加括号,如下:

posInList : Id -> Maybe (List (Id, ItemModel)) -> Int

但后来我得到了:

enter image description here

现在我很无能,从未见过这样的错误。

2 个答案:

答案 0 :(得分:2)

首先,它可能有助于将其分解为更简单的indexOf函数,以避免必须处理您正在使用的特定元组模型。这使它更清洁,更可重复使用。

我们将indexOf定义为:

indexOf : a -> List a -> Maybe Int
indexOf el list =
  let
    indexOf' list' index =
      case list' of
        [] ->
          Nothing
        (x::xs) ->
          if x == el then
            Just index
          else
            indexOf' xs (index + 1)
  in
    indexOf' list 0

这里没什么特别的,它只是模式匹配和递归调用。子函数indexOf'用于跟踪当前索引。

现在我们有一个通用indexOf函数,可用于任何类似的类型,而不仅仅是整数。

接下来,我们需要挤入类型List (Id, ItemModel)的列表。我们可以在fst函数中使用map,创建Id的列表。

posInList : Id -> List (Id, ItemModel) -> Int
posInList id list =
  case indexOf id (List.map fst list) of
    Nothing ->
      -1
    Just index ->
       index

在未找到某些内容的情况下,您的原始实现返回-1,但我认为返回Maybe Int会更加惯用。这样可以清楚地表明你对使用该库的其他人的意图。

答案 1 :(得分:0)