0

I'm trying to return a Maybe value from a function that uses do notation, but I can't seem to get it to work. This function takes a string (The "filename") and a Path to search in...

findIn :: String -> Path -> Maybe Path
findIn search start = do
    file <- ls start
    if ((filename file) == search)
      then Just file
      else Nothing

Where...

ls :: Path -> Array Path
filename :: Path -> String

But I keep getting the error "Count not match Type Array with type Maybe", so it looks like the compiler is expecting the do notation to return an array. How would I return a maybe value?

Albtzrly
  • 924
  • 1
  • 6
  • 15

2 Answers2

2

You can't mix monads like that.

When you write:

file <- ls start

it's a bit like saying "for each value file in the array..." so you are in the context of multiple possible values.

But then the rest of the code is in the context of Maybe, which can only handle one (or zero) values.

In the module Data.Foldable there is a find function, which does the bulk of the work of your main function, by searching for a single item that matches some criteria. Its actual type is more general, but when constrained to Arrays it's like this:

find :: forall a. (a -> Boolean) -> Array a -> Maybe a

Then you can just write:

findIn search start = find (\x => x == search) $ ls start
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • 1
    Ok, I think I understand. So do notation has to return an array, and all the expressions are aimed at doing filtering and mapping on those arrays. – Albtzrly Apr 03 '16 at 01:54
  • 1
    Yes that's right. If you want to return a `Maybe` then the `do` block needs to be all about `Maybe`. I've updated my answer a little. – Peter Hall Apr 03 '16 at 02:02
  • Thanks for clarifying that. That note about being in the "context of Maybe" and in the "context of multiple possible values" make sense. I haven't thought about it in that way before. – Albtzrly Apr 03 '16 at 02:22
1

Ok, I found something that works, but I'm not sure if it's ideal.

findIn :: String -> Path -> Maybe Path
findIn search start = if (length r == 1)
                      then head r
                      else Nothing
  where
    r = do
      file <- ls start
      guard $ (filename file) == search
      [file]

So it looks like the do-notation returns a value of type Array(Maybe Path) .

Albtzrly
  • 924
  • 1
  • 6
  • 15