Haskell:在元组列表上使用`find`函数

问题描述 投票:-1回答:4

我想知道是否有人可以帮助我。假设我有一个类型为(String,Int)的元组,以及此类元组的列表[("Strength",12),("Stamina",60),("Health",100)]

如果我实际上不知道元组在列表中的顺序,而是仅知道某个包含字符串find的元组,那么如何使用函数Int提取元组("Stamina",60)"Stamina"值]存在?

我尝试过

value =   snd ( find ("Stamina", _ ) stats )

其中stats是元组列表,value定义为

  value :: a -> Int    

..但是不起作用:/那么有什么想法吗?我特别打算使用find

list haskell find tuples
4个回答
7
投票

似乎您正在尝试使用模式作为find的参数。不幸的是,这行不通。您只能在几个地方进行模式匹配,例如后卫和case表达式。

正如Jubobs在他的评论中所说,在这种情况下使用Data.List.lookup是理想的,但是当然也可以使用Data.List.find

[如果查看Data.List.find的类型,您会发现它看起来像这样:

find :: Foldable t => (a -> Bool) -> t a -> Maybe a 

这告诉您两件重要的事情:

  1. 第一个参数必须是谓词函数,即,当参数为您要查找的值时返回True的函数,否则返回False

  2. 该函数返回一个Maybe a,这意味着它可能返回Nothing,因此您必须对此进行处理。

创建谓词功能非常容易。您只需要使用==运算符来测试元组的第一个值的东西,也许是像这样的lambda函数:

\(x, _) -> x == "Stamina"

现在您可以像这样呼叫find

find (\(x, _) -> x == "Stamina") stats

或者,您可以创建一个通用函数来将元组的第一个元素与已知值进行比较,例如:

matchFirst x (y, _) = x == y

稍后使用matchFirst函数作为find的参数:

find (matchFirst "Stamina") stats

现在让我们看我的第二点:您如何处理find找不到任何东西?

如果您完全确定它将始终成功,则可以像下面这样简单地使用Data.Maybe.fromJustMaybe中提取元组:

value = snd $ fromJust $ find (matchFirst "Stamina") stats

否则,如果查找实际上可能失败,则可以执行许多操作。例如,您可以在Data.Maybe.fromMaybe中使用合理的默认值,也可以将value更改为Maybe Int类型。

最后,最后一件事:您说过value具有类型a -> Int,即,一个接受任何内容并返回Int的函数。实际上并非如此。相反,它只是一个值。


0
投票

更多替代方案,不一定比上述替代方案更好:

根据OP的建议使用模式

find (\c -> case c of ("A", _) -> True ; _ -> False) [("B",4), ("A", 5), ("C", 7)]

同样,利用扩展名

{-# LANGUAGE LambdaCase #-}
find (\case ("A", _) -> True ; _ -> False) [("b",4), ("A", 5), ("C", 7)]

0
投票

这里使用fst和等式==的简单单线。

您需要导入Data.ListData.Maybe

> let set stats = [("Strength",12),("Stamina",60),("Health",100)]
> snd $ fromJust $ find ((=="Strength") . fst) stats
12

0
投票
fn :: Eq a => a -> [(a, b)] -> b
fn x = snd . fromJust . find ((== x) . fst)

那么您将有

tuples :: [(String, Int)]
tuples = undefined  -- a list of tuples

string :: String
string = "Stamina"

value :: Int
value = fn string tuples 
© www.soinside.com 2019 - 2024. All rights reserved.