Q_96
Q_96

Reputation: 95

First element in a list haskell

So i need to do a find2 method that take the first Element out.

For example find2 :: (a -> Bool) -> [a] -> a

and find2 (>4) [1 .. 10]

Should have a the output 5

I am not good with haskell, but i want to learn it.

My first try was

find2 :: (a -> Bool) -> [a] -> a
find2 p [] = []
find2 p (x:xs)
 |p x = x+1
 |otherwise = finde p xs

but i am getting an error

 * Couldn't match expected type `a' with actual type `[a0]'
      `a' is a rigid type variable bound by
        the type signature for:
          find2 :: forall a. (a -> Bool) -> [a] -> a
        at C:\\Users\XY\Desctop\XY.hs:30:1-32
    * In the expression: []
      In an equation for `find2': find2 p [] = []
    * Relevant bindings include
        p :: a -> Bool
          (bound at C:\\Users\XY\Desctop\XY.hs:31:7)
        find2 :: (a -> Bool) -> [a] -> a
          (bound at C:\\Users\XY\Desctop\XY.hs:31:1)

Upvotes: 6

Views: 26494

Answers (2)

Russell Emerine
Russell Emerine

Reputation: 61

If you're ok with erroring when the list contains no satisfactory elements, you can do this:

find p xs = head (filter p xs)

or the equivalent point-free, which I like more

find p = head . filter p

(not this though, it's over the top)

find = (head .) . filter -- obscure, not a good choice

If you want to return it in a Maybe, you can import Data.Maybe and do this:

find p = listToMaybe . filter p

If you want it in a list, this never errors:

find p = take 1 . filter p

You can use dropWhile (not . p) instead of filter p if you like, too.

Manually defining the recursion is fine too, but I think it's work that isn't necessary.

Upvotes: 3

Alejandro De Cicco
Alejandro De Cicco

Reputation: 1236

There is a problem here. There might not be a value in your list for which p holds true. You can see that problem in the base case of your function, when you return an empty list. However, you declared your function to return a single a value, and not a list.

Because of that, you need a way to differentiate a found value from an empty value. For this you can declare your function to return Maybe a instead of a. That way, when you reach the empty list case, you can return Nothing, and if you find the element you were looking for you can return Just x. It would look like this:

find2 :: (a -> Bool) -> [a] -> Maybe a
find2 p [] = Nothing
find2 p (x:xs)
 |p x = Just x
 |otherwise = find2 p xs

If you're not familiar with the Maybe type, you can read more about it here

Upvotes: 6

Related Questions