I am trying to convert a Maybe Int to an Int in Haskell like this:
convert :: Maybe Int -> Int
convert mx = case mx of
Just x -> x
Nothing -> error "error message"
When I compile it, Haskell tells me: parse error on input 'Nothing'.
I need this, because I want to get the Index of an element in a list with the elem.Index function from the Data.List module and then use this index on the take function. My problem is that elemIndex returns a Maybe Int, but take needs an Int.
This is a whitespace problem. The case clauses need to be indented to the same level.
convert :: Maybe Int -> Int
convert mx = case mx of
Just x -> x
Nothing -> error "error message"
Remember to use only spaces, no tabs.
To add to #leftaroundabout's answer, I think I might provide you with some other options.
First off, you shouldn't make unsafe things like this: your program will fail. It's much cleaner to keep it as a Maybe Int and operate as such, safely. In other words, this was a simple parse error, but making incomplete functions like this may cause far greater problems in the future.
The problem you've encountered it, how can I do that?
We might make a better function, like this:
mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe f m = case m of
Just a -> f a
Nothing -> Nothing
Which would allow you to write:
λ> (+ 15) `mapMaybe` Just 9
Just 24
However, there is a function called fmap, which 'maps' a function over certain data-structures, Maybe included:
λ> (== 32) `fmap` Just 9
Just False
and if you have imported Control.Applicative, there is a nice operator synonym for it:
λ> show <$> Just 9
Just "9"
If you want to know more about these data-structures, called Functors, I would recommend reading Learn-you a Haskell.
Related
So I have to define a safe version of the head function that would not throw an error when [] is passed as the argument. Here it is:
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x
But now, is this function still of any use? Because suppose that type "a" is a Int, then you can add two objects of type Int, but you can't add two objects of type "Maybe Int".
As it was mentioned in comments, you can actually add two Maybes. I just wanted to give another point of view on that.
Yes, you can't directly apply (+) to Maybe Ints, but you can upgrade it to another function that is able to do so automatically.
To upgrade unary function (like (+1)) you write fmap (+1) maybeInt or (+1) <$> maybeInt. If (+1) had type Int -> Int, the fmap (+1) expression has type Maybe Int -> Maybe Int.
Upgrading bin-or-more-ary functions is a bit more complex syntax-wise: (+) <$> maybeInt <*> maybeInt or liftA2 (+) maybeInt maybeInt. Again, here we promote (+) :: Int -> Int -> Int to liftA2 (+) :: Maybe Int -> Maybe Int -> Maybe Int.
Handling Maybes this way allows you to build up a computation that works with Maybes out of pure functions and defer checking for Nothing. Or even avoid that if you eventually plug it into another function that takes Maybe as argument.
Of course, you can use fmap and liftAs on any Applicative, not just Maybe.
"Just" is one such function. Here's how you can use its result (for the ghci REPL):
import Data.Foldable (sequenceA_)
let writeLn = putStrLn . show
let supposedlyUnusable = writeLn <$> Just 0
sequenceA_ supposedlyUnusable
which prints 1 or we can continue to try the other interesting example - using the Nothing case
let supposedlyUnusable = writeLn <$> Nothing
sequenceA_ supposedlyUnusable
which doesn't print anything.
That's a complete program which works even for other instances of Traversable or Foldable where you couldn't do a case analysis on the Maybe value. <$> is the key that lets you apply a function to whatever's contained in the Maybe or any Functor and if you have two Maybes (or two of the same Applicative) you can use the pattern fn <$> applicative_a <*> applicative_b which is like fn a b but where a and b are wrapped up things like Maybe values.
So that leaves a couple of remaining ways to use a Maybe that I can think of, all of which use case analysis:
let {fn (Just n) = Just $ 1 + n; fn Nothing = Nothing}
fn v
-- but that was just a messy way of writing (1+) <$> v
...
let fn v = case v of {Just n -> Just $ 1 + n; Nothing -> Nothing}
-- and that's the same program with a different syntax
...
import Data.Maybe (fromMaybe)
fromMaybe someDefault v
-- and that extracted the `value` from `v` if we had `Just value` or else gave us `someDefault`
...
let {fn (Just n) = writeLn n; fn Nothing = putStrLn "No answer"}
-- this one extracts an action but also provides an action when there's nothing
-- it can be done using <$> and fromMaybe instead, but beginners tend to
-- find it easier because of the tutorials that resulted from the history
-- of the base library's development
let fn v = fromMaybe (putStrLn "No answer") (writeLn <$> v)
oooh, oooh! This one's neato:
import Control.Applicative
let v = Just 0 -- or Nothing, if you want
let errorcase = pure $ putStrLn "No answer"
let successcase = writeLn <$> v
sequenceA_ $ successcase <|> errorcase
-- that uses Alternative in which Maybe tries to give an answer preferring the earliest if it can
of course we also have the classic:
maybe (putStrLn "No answer") writeLn v
Safety comes with a cost. The cost is normally extra code, for avoiding error situations. Haskell has given us the way to avoid this at the compile time rather than at run time.
Let me explain with examples from other languages. Though I won't name any language, but it would be apparent which languages I am talking about. Please be sure that all languages are great in their ways, so do not take this as I am finding fault in other language.
In some languages you have pointers and the way you will do safeHead is to return either int pointer or null pointer. You will have to de-reference pointer to get the value and when you de-reference null pointer you will get error. To avoid this, extra code will be needed to check for null pointer, and do something when it is null.
In some dynamic languages, you have variables assigned to null. So in above example your variable could be type int or it could be null. And what will happen if you add null to int? Most probably undefined situation. Again special handling needs to be done for the null case.
In Haskell too you will have to do the same, you will have to guard the null situation with extra code. So what's the difference? The difference in Haskell is doing it at the compile time and not at the run time.* i.e. the moment you have this kind of code along with your definition of safeHead, p = safeHead xs + safeHead ys, the code will give error at the compile time. You will have to do something more for addition if type Maybe Int. You can write your function for adding two or multiple Maybe Ints or create newype for Maybe Int and overload + or do something as mentioned in other answers.
But whatever you do, you do it before unit testing. Definitely much before it goes on production. And earlier the error is caught lesser is the cost. That's where the advantage of type safe Haskell comes in handy.
* There could be mechanism in other languages to handle this at compile time.
I've just started with Haskell and have to solve the following task.
I have a list which contains weekdays and I need the index corresponding to the location of the value st if it is found in the list:
weekdays = ["Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag"]
findIndex(==st)weekdays
My code works so far, that i get Just 3 for example. However, I read, that this is a Maybe Int and I need just the number out of it.
So, I added a function eliminate:
eliminate :: Maybe Int -> Int
eliminate (Just a) = a
But if I use eliminate findIndex(==st)weekdays it doesn't work and the error is:
*** Expression : eliminate findIndex (flip (==) st) weekdays
*** Term : eliminate
*** Type : Maybe Int -> Int
*** Does not match : a -> b -> c -> d
And I can't figure out a way to go from here, since I'm a beginner.
Can someone help me out? The code has to work on Hugs98 unfortunately.
Note that the type error reported by Hugs relates to associativity and precedence of function application. Your expression
eliminate findIndex (== st) weekdays
attempts to apply eliminate to findIndex first, which is not the intent of your code. I think what you really want to do is:
eliminate (findIndex (== st) weekdays)
or
eliminate $ findIndex (== st) weekdays
These both apply eliminate to the result of findIndex (== st) weekdays. This should type-check as expected.
But, in answer to your question about how to deal with the Maybe value: you can use fromJust or fromMaybe to extract the contained value.
The links go to the current GHC documents but there should be equivalent Hugs functions.
Here's a hint for future use: you can search the Haskell documentation online using Hoogle. The best thing is that you can search both by function name and by type signature. For example, searching by Maybe a -> a would've found both these functions.
Another approach is to pattern-match on Nothing as well as Just a:
eliminate (Just a) = -- Handle a
eliminate Nothing = -- Handle error case
Of course, then you have to decide what eliminate should evaluate to in the error case.
I have a function that has a return type of Maybe ([(Int,Int)],(Int,Int))
I would like to call this from another function and perform an operation on the data.
However, the return value is contained within Just. The second method takes ([(Int,Int)],(Int,Int)) and therefore will not accept Just ([(Int,Int)],(Int,Int)).
Is there a way I can trim the Just before applying the second method?
I don't fully understand the use of Just within Maybe - however, I have been told that the return type for the first Method must be Maybe.
There are several solutions to your problem, all based around pattern matching. I'm assuming you have two algorithms (since you didn't name them, I will):
algorithm1 :: a -> Maybe b
algorithm2 :: b -> c
input :: a
1) Pattern matching is typically done from either a case statement (below) or a function.
let val = algorithm1 input
in case val of
Nothing -> defaultValue
Just x -> algorithm2 x
All other presented solutions use pattern matching, I'm just presenting standard functions that perform the pattern matching for you.
2) The prelude (and Data.Maybe) have some built-in functions to deal with Maybes. The maybe function is a great one, I suggest you use it. It's defined in standard libraries as:
maybe :: c -> (b -> c) -> Maybe b -> c
maybe n _ Nothing = n
maybe _ f (Just x) = f x
Your code would look like:
maybe defaultValue algorithm2 (algorithm1 input)
3) Since Maybe is a functor you could use fmap. This makes more sense if you don't have a default value. The definition:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
So your code would look like:
fmap algorithm2 (algorithm1 input)
This output will be a Maybe value (Nothing if the result of algorithm1 is Nothing).
4) Finally, and strongly discouraged, is fromJust. Only use it if you are positive the first algorithm will return Just x (and not Nothing). Be careful! If you call fromJust val when val = Nothing then you get an exception, which is not appreciated in Haskell. Its definition:
fromJust :: Maybe b -> b
fromJust Nothing = error "Maybe.fromJust: Nothing" -- yuck
fromJust (Just x) = x
Leaving your code to look like:
algorithm2 (fromJust (algorithm1 input))
You're looking for fromJust. But only if you're certain your Maybe function is not going to return a Nothing!
I've just started trying to learn haskell and functional programming. I'm trying to write this function that will convert a binary string into its decimal equivalent. Please could someone point out why I am constantly getting the error:
"BinToDecimal.hs":19 - Syntax error in expression (unexpected `}', possibly due to bad layout)
module BinToDecimal where
total :: [Integer]
total = []
binToDecimal :: String -> Integer
binToDecimal a = if (null a) then (sum total)
else if (head a == "0") then binToDecimal (tail a)
else if (head a == "1") then total ++ (2^((length a)-1))
binToDecimal (tail a)
So, total may not be doing what you think it is. total isn't a mutable variable that you're changing, it will always be the empty list []. I think your function should include another parameter for the list you're building up. I would implement this by having binToDecimal call a helper function with the starting case of an empty list, like so:
binToDecimal :: String -> Integer
binToDecimal s = binToDecimal' s []
binToDecimal' :: String -> [Integer] -> Integer
-- implement binToDecimal' here
In addition to what #Sibi has said, I would highly recommend using pattern matching rather than nested if-else. For example, I'd implement the base case of binToDecimal' like so:
binToDecimal' :: String -> [Integer] -> Integer
binToDecimal' "" total = sum total -- when the first argument is the empty string, just sum total. Equivalent to `if (null a) then (sum total)`
-- Include other pattern matching statements here to handle your other if/else cases
If you think it'd be helpful, I can provide the full implementation of this function instead of giving tips.
Ok, let me give you hints to get you started:
You cannot do head a == "0" because "0" is String. Since the type of a is [Char], the type of head a is Char and you have to compare it with an Char. You can solve it using head a == '0'. Note that "0" and '0' are different.
Similarly, rectify your type error in head a == "1"
This won't typecheck: total ++ (2^((length a)-1)) because the type of total is [Integer] and the type of (2^((length a)-1)) is Integer. For the function ++ to typecheck both arguments passed to it should be list of the same type.
You are possible missing an else block at last. (before the code binToDecimal (tail a))
That being said, instead of using nested if else expression, try to use guards as they will increase the readability greatly.
There are many things we can improve here (but no worries, this is perfectly normal in the beginning, there is so much to learn when we start Haskell!!!).
First of all, a string is definitely not an appropriate way to represent a binary, because nothing prevents us to write "éaldkgjasdg" in place of a proper binary. So, the first thing is to define our binary type:
data Binary = Zero | One deriving (Show)
We just say that it can be Zero or One. The deriving (Show) will allow us to have the result displayed when run in GHCI.
In Haskell to solve problem we tend to start with a more general case to dive then in our particular case. The thing we need here is a function with an additional argument which holds the total. Note the use of pattern matching instead of ifs which makes the function easier to read.
binToDecimalAcc :: [Binary] -> Integer -> Integer
binToDecimalAcc [] acc = acc
binToDecimalAcc (Zero:xs) acc = binToDecimalAcc xs acc
binToDecimalAcc (One:xs) acc = binToDecimalAcc xs $ acc + 2^(length xs)
Finally, since we want only to have to pass a single parameter we define or specific function where the acc value is 0:
binToDecimal :: [Binary] -> Integer
binToDecimal binaries = binToDecimalAcc binaries 0
We can run a test in GHCI:
test1 = binToDecimal [One, Zero, One, Zero, One, Zero]
> 42
OK, all fine, but what if you really need to convert a string to a decimal? Then, we need a function able to convert this string to a binary. The problem as seen above is that not all strings are proper binaries. To handle this, we will need to report some sort of error. The solution I will use here is very common in Haskell: it is to use "Maybe". If the string is correct, it will return "Just result" else it will return "Nothing". Let's see that in practice!
The first function we will write is to convert a char to a binary. As discussed above, Nothing represents an error.
charToBinary :: Char -> Maybe Binary
charToBinary '0' = Just Zero
charToBinary '1' = Just One
charToBinary _ = Nothing
Then, we can write a function for a whole string (which is a list of Char). So [Char] is equivalent to String. I used it here to make clearer that we are dealing with a list.
stringToBinary :: [Char] -> Maybe [Binary]
stringToBinary [] = Just []
stringToBinary chars = mapM charToBinary chars
The function mapM is a kind of variation of map which acts on monads (Maybe is actually a monad). To learn about monads I recommend reading Learn You a Haskell for Great Good!
http://learnyouahaskell.com/a-fistful-of-monads
We can notice once more that if there are any errors, Nothing will be returned.
A dedicated function to convert strings holding binaries can now be written.
binStringToDecimal :: [Char] -> Maybe Integer
binStringToDecimal = fmap binToDecimal . stringToBinary
The use of the "." function allow us to define this function as an equality with another function, so we do not need to mention the parameter (point free notation).
The fmap function allow us to run binToDecimal (which expect a [Binary] as argument) on the return of stringToBinary (which is of type "Maybe [Binary]"). Once again, Learn you a Haskell... is a very good reference to learn more about fmap:
http://learnyouahaskell.com/functors-applicative-functors-and-monoids
Now, we can run a second test:
test2 = binStringToDecimal "101010"
> Just 42
And finally, we can test our error handling system with a mistake in the string:
test3 = binStringToDecimal "102010"
> Nothing
I have a function that has a return type of Maybe ([(Int,Int)],(Int,Int))
I would like to call this from another function and perform an operation on the data.
However, the return value is contained within Just. The second method takes ([(Int,Int)],(Int,Int)) and therefore will not accept Just ([(Int,Int)],(Int,Int)).
Is there a way I can trim the Just before applying the second method?
I don't fully understand the use of Just within Maybe - however, I have been told that the return type for the first Method must be Maybe.
There are several solutions to your problem, all based around pattern matching. I'm assuming you have two algorithms (since you didn't name them, I will):
algorithm1 :: a -> Maybe b
algorithm2 :: b -> c
input :: a
1) Pattern matching is typically done from either a case statement (below) or a function.
let val = algorithm1 input
in case val of
Nothing -> defaultValue
Just x -> algorithm2 x
All other presented solutions use pattern matching, I'm just presenting standard functions that perform the pattern matching for you.
2) The prelude (and Data.Maybe) have some built-in functions to deal with Maybes. The maybe function is a great one, I suggest you use it. It's defined in standard libraries as:
maybe :: c -> (b -> c) -> Maybe b -> c
maybe n _ Nothing = n
maybe _ f (Just x) = f x
Your code would look like:
maybe defaultValue algorithm2 (algorithm1 input)
3) Since Maybe is a functor you could use fmap. This makes more sense if you don't have a default value. The definition:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
So your code would look like:
fmap algorithm2 (algorithm1 input)
This output will be a Maybe value (Nothing if the result of algorithm1 is Nothing).
4) Finally, and strongly discouraged, is fromJust. Only use it if you are positive the first algorithm will return Just x (and not Nothing). Be careful! If you call fromJust val when val = Nothing then you get an exception, which is not appreciated in Haskell. Its definition:
fromJust :: Maybe b -> b
fromJust Nothing = error "Maybe.fromJust: Nothing" -- yuck
fromJust (Just x) = x
Leaving your code to look like:
algorithm2 (fromJust (algorithm1 input))
You're looking for fromJust. But only if you're certain your Maybe function is not going to return a Nothing!