简体   繁体   中英

Haskell - How to get index of elem in list?

I want to get an index of elem in list? Not Maybe Int, only int.

>elemIndex 'f' "BarFoof"
>Just 6

But need 6

You can use fromMaybe:: a -> Maybe a -> a to unwrap the value from a Just , and furtermore add a default value in case it is a Nothing .

So you can implement a function:

import Data.Maybe()

elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x =  . elemIndex x

Here it will thus return -1 in case the element can not be found. For example:

Prelude Data.Maybe Data.List> elemIndex' 'f' "BarFoof"
6
Prelude Data.Maybe Data.List> elemIndex' 'q' "BarFoof"
-1

That being said, in Haskell a Maybe is often used to denote a computation that might "fail", such that if you post-process the result, you will take the Nothing (element not found in the list) into account as well.

As Willem Van Onsem says, you can use fromMaybe . However, there are other options which may be better suited to your particular use case. (It's not clear from your code what your use case is, though, so I'm just going to list some options.)

If you know for certain that the value you're looking for is going to be somewhere in the list, usually because you've just pulled it out of the same list using some sort of fold, you can use fromJust . fromJust is similar to fromMaybe , except it doesn't take the additional first argument as a fallback value and instead will throw an error if the value isn't in the list. People will argue about whether or not you should use functions that can throw an error (these functions are called "partial," because they only handle part of their input domain) because they can really cause headaches down the line when assumptions turn out to be wrong, but in carefully controlled circumstances they can be useful.

fromJust (Just 10)
> 10

fromJust Nothing
> *** Exception: Maybe.fromJust: Nothing

Depending on the semantics of your program, it may also be more idiomatic to change your function signature to return a Maybe whatever instead of a whatever . In this case, you should look into using things like fmap , >>= , and <$> to pass your value around without ever needing to unwrap it. I can't tell you if this is the right approach for your program in particular without seeing more of your code, but for most use cases, fromMaybe is not the right approach.

fmap (+ 5) (Just 10)
> Just 15

fmap (+ 5) Nothing
> Nothing

Just 10 <$> (+ 5)
> Just 15

Nothing <$> (+ 5)
> Nothing

Just 10 >>= (\x -> if even x then Just $ x `div` 2 else Nothing)
> Just 5

Just 5  >>= (\x -> if even x then Just $ x `div` 2 else Nothing)
> Nothing

Nothing >>= (\x -> if even x then Just $ x `div` 2 else Nothing)
> Nothing

Using a value like -1 to indicate failure means that the rest of your program needs to know that -1 indicates a failure state. These sorts of failure values usually need to be handled separately from normal return values, which is exactly the use case that the Maybe type is designed to make more elegant. The quick test for whether you should be unwrapping a Maybe is to look and see if there is anywhere in your program where you are pattern matching (or using guards or if or case , etc.) to try to catch this -1 somewhere else to trigger specialized behavior. If you are, then you shouldn't be unwrapping Maybe (here).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM