英文:
Mapping an Either list to integers
问题
我正在尝试完成以下操作:
processRights :: [Either a Int] -> Int
processRights xs = map (\Right x -> x, \Left x -> 0) xs
所以,xs
是 [Either a Int]
,我希望生成一个相同长度的映射列表,对于每个 int,都有相同的 int,否则为 0。
我该如何实现这一点?
英文:
I am trying to do the following:
processRights :: [Either a Int] -> Int
processRights xs = map (\Right x -> x, \Left x -> 0) xs
So, xs
is a [Either a Int]
, and I wish to produce a mapped list of the same length where for each int there is the same int, 0 otherwise.
How can I acomplish that?
答案1
得分: 6
你可以使用 either
、id
和 const
函数:
processRights :: [Either a Int] -> [Int]
processRights = map $ either (const 0) id
either
对于任何 Left
运行第一个函数,对于任何 Right
运行第二个函数。
id
返回其参数。
const
忽略其第二个参数并返回其第一个参数,其预期用途是,例如 const 0
变成一个忽略其参数并只返回 0 的函数。
英文:
You can use the either
, id
and const
functions:
processRights :: [Either a Int] -> [Int]
processRights = map $ either (const 0) id
either
runs the first function for any Left
, the second function for any Right
.
id
returns its argument.
const
ignores its second argument and returns its first argument, its intended use is that e.g. const 0
becomes a function that ignores its argument and just returns 0.
答案2
得分: 2
以下是翻译好的部分:
你提出的代码实际上非常接近了!以下是一个可以工作的版本,只需要进行最小的更改:
processRights xs = map (\case Right x -> x; Left x -> 0) xs
你需要启用 LambdaCase
语言扩展。(当然,正如其他答案中提到的,还有更符合惯用方式来实现这个效果的方法。)
英文:
Your proposed code is really, really close, actually! Here's a working version with minimal changes:
processRights xs = map (\case Right x -> x; Left x -> 0) xs
You will need to turn on the LambdaCase
language extension. (And of course, as mentioned in other answers, there are more idiomatic ways to achieve this effect.)
答案3
得分: 1
A clear way to do this is to work with a helper function. Indeed:
processRights :: [Either a Int] -> [Int]
processRights = map go
where go (Right x) = x
go (Left _) = 0
This is not the most concise way, but it shows what is happening. You can simplify this with fromRight :: b -> Either a b -> b
where we provide a value to use or a Left x
element, and it will thus either select that value, or the value wrapped in the Right
data constructor, so:
import Data.Either(fromRight)
processRights :: Num b => [Either a b] -> [b]
processRights = map (fromRight 0)
英文:
A clear way to do this is to work with a helper function. Indeed:
processRights :: [Either a Int] -> [Int]
processRights = map go
where go (Right x) = x
(Left _) = 0
This is not the most concise way, but it shows what is happening. You can simplify this with fromRight :: b -> Either a b -> b
where we provide a value to use or a Left x
element, and it will thus either select that value, or the value wrapped in the Right
data constructor, so:
import Data.Either(fromRight)
processRights :: Num b => [Either a b] -> [b]
processRights = map (fromRight 0)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论