0

I'm working on Learn You a Haskell. On the "fold" section, I need to implement elem (given an element, find out if it's in the list - True or False).

def myElem(a: Char, as: List[Char]): Boolean = as match {
   case Nil => false
   case x::Nil => println(x); if(x == a) true else false
   case x::_ => println(x); as.foldLeft(false){ (_, elem) => 
                   if(a == elem) true
                   else myElem(a, as.tail)

   }
}

However, it's failing on a simple example:

scala> myElem('a', "ab".toList)
a
b
res8: Boolean = false

What am I doing wrong here? Also, as extra, I'd appreciate any suggestion on improvement of this code.

As an aside, I would think a find would be more appropriate here.

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

1 Answers1

2

This is a pretty simple implementation:

  def elem[A](a: A, as: List[A]): Boolean = as match {
    case Nil => false
    case h :: t => (h == a) || elem(a, t)
  }

Also, instead of find you could use exists:

def elem[A](a: A, as: List[A]) = as.exists(_ == a)

If you want to foldLeft you can, but you'll still traverse the whole list instead of stopping early:

  def elem[A](a: A, as: List[A]) = 
    as.foldLeft(false)((bool, value) => bool || value == a)
Noah
  • 13,821
  • 4
  • 36
  • 45
  • Yes - it's clean - thanks. what about using `foldLeft` though? – Kevin Meredith Apr 18 '14 at 03:16
  • @KevinMeredith I updated the answer, you can use foldLeft, but I wouldn't if your lists are long. – Noah Apr 18 '14 at 03:20
  • Looking at the LYAH version that I converted to Scala: `def myElem[A](a: A, as: List[A]): Boolean = { as.foldLeft(false){ (acc, elem) => if(elem == a) true else acc } }`, I like your version too as it will short-circuit if the `accumulator` (or `bool` as you call it) is true. – Kevin Meredith Apr 18 '14 at 03:39