Haskell passing empty Character to a function

10,071

Solution 1

You can use a Maybe:

before :: Char -> [Char] -> Maybe Char
before x str = initialise x str

initialise x (y:xs)
  | x == y = Nothing
  | otherwise = trackelement x y xs

trackelement :: Char -> Char -> [Char] -> Maybe Char
trackelement x y [] = Nothing
trackelement x y (z:zs)
  | x == z = Just y
  | otherwise = trackelement x z zs

To take care of the corner case before 'l' "luis", we have to add a new initialiser function. It basically checks if the first character matches the searched one. If it does, we return Nothing, because we checked the first character which obviously does not have a preceding one. Else we just call trackelement and use it's result.


As Zeta mentioned, you can combine the functions, which simplifies everything and takes care of the corner case you are currently experiencing.

before _ [x] = Nothing
before a (x:y:xs)
  | a == y = Just x
  | otherwise = before a (y:xs)

Just using this function, you noticed you have problems when encountering a word containing more than one letter which is also searched for (before 'a' "amalia" -> Just 'm'). Currently the best solution I know of is again splitting this up into more than one function, which brings us back to the solution at the top.

Solution 2

The answers shown already are good for getting your code to work, but they don't explain why you get the error you're receiving. The reason why that error was shown is that '' is not valid syntax, since there is no such thing as an "empty character". All characters have value, but Strings can be empty. Remember that type String = [Char], and it's very clear that there can be such a thing as an empty list, but characters always have a value. It's comparable to saying you can have an empty list of Ints, namely [], but you can't have an "empty int", whatever that would mean.

Solution 3

Match the first two elements instead just head and tail. That way you don't even need trackelement:

before :: Eq a => a -> [a] -> Maybe a
before x (a:b:rest)
   | a == x    = Nothing
   | b == x    = Just a
   | otherwise = before x (b:rest)
before _ _ = Nothing
Share:
10,071
Luis Armando
Author by

Luis Armando

Updated on June 04, 2022

Comments

  • Luis Armando
    Luis Armando over 1 year

    I'm working in Haskell in two functions:

    Basically I want to get the character before matching a specific character in a given string

    This is my code:

    before :: Char -> [Char] -> Char
    before x str = trackelement x ' ' str
    
    trackelement :: Char -> Char -> [Char] -> Char
    trackelement x y (z:zs)
        | x == z = y
        | otherwise = trackelement x z (zs) 
    

    My problem is when I try: before 'l' "luis"

    The answer is : ' ' (of course, before 'l' there is nothing), and I would like to be '' or Nothing

    I tried passing trackelement x '' str instead of trackelement x ' ' str but I have this error Syntax error on ''str

    Could you suggest me something?

  • Luis Armando
    Luis Armando about 9 years
    I have tried your solution, but the result is Just 'l' or Just ' ' I need only the 'l' or ''. I never worked with Maybe
  • Zeta
    Zeta about 9 years
    Actually, the question was edited and the problem wasn't in there at the time we wrote the answers ^^".
  • ThreeFx
    ThreeFx about 9 years
    @LuisArmando The problem is that a possible match is given at the beginning. Combining the functions as Zeta did is the best practice.
  • bheklilr
    bheklilr about 9 years
    @Zeta Ah, I had not realized. Regardless, I just wanted to see it addressed. Personally, I think your answer provides the best solution for getting a working algorithm (ThreeFx's is good, but is a little lengthy in comparison), I just wanted all bases to be covered so that OP understood more fully what was going on.
  • Luis Armando
    Luis Armando about 9 years
    your answer is not working properly I tried before 'a' "amalia" and the response was Just 'm'. This is wrong because it have to match with the first 'a' not with the latest ;)
  • ThreeFx
    ThreeFx about 9 years
    @LuisArmando `´Just 'm'`` is the middle 'a' ^^ This happens because the checking starts too late.
  • chi
    chi about 9 years
    I'd add a case for the empty list in before.