At HaskellWiki's Do notation considered harmful, section Useful applications, I found:
It shall be mentioned that the do sometimes takes the burden from you
to write boring things.
E.g. in
getRight :: Either a b -> Maybe b
getRight y =
do Right x <- y
return x
a case on y is included, which calls fail if y is not a Right (i.e.
Left), and thus returns Nothing in this case.
Calling fail (Nothing) on a pattern mismatch sounds interesting, so I wanted to try this out. However, the syntax looks wrong - we're not in the Either monad, so how can we extract anything from y?
Indeed, I tried and it gave me "Couldn't match type `Either a' with `Maybe'". So let's use the correct pattern matcher, let in here:
getRight y = do { let (Right x) = y; return x }
That gave me a syntax error "parse error on input `}'". Not that I understand why this doesn't work, but let's write it out in multiline notation:
getRight y = do
let (Right x) = y
return x
Ah, that seemed to work - parse at least. However:
*Main> getRight (Right 5)
Just 5
*Main> getRight (Left 5)
Just *** Exception: […]\test.hs:16:13-25: Irrefutable pattern failed for pattern (Data.Either.Right x)
-- `Nothing` was expected
What gives? So my questions are now:
What happened here? Why did my semicolon-brace line not work?
How to do it correctly (with do, everything else is trivial)?
The example is probably meant to be
getRight :: Either a b -> Maybe b
getRight y =
do Right x <- return y -- note: return = Just
return x
where the pattern match failure calls fail = const Nothing. It is translated into:
getRight y = let ok (Right x) = do {return x}
ok _ = fail "pattern mismatch error"
in return y >>= ok
FWIW most experienced folks seem to think fail as a Monad method was a wart. Check out MonadPlus for a maybe more principled approach to failure.
Related
I'm still new to Haskell. Whats the best way to distinguish between errors?
Currently I'm using the maybe monad but it can only 'represent one state of error'.
The following code snippet will put my question into context.
pulOh :: Seq -- input X O sequence
-> Int -- split point real index
-> Maybe Seq
pulOh xs n =
case (\(f,l)->(tlTrn f, hdTrn l)) (splSq xs n) of -- split and process at index
(Nothing, _) -> Nothing -- first failed
(_, Nothing) -> Nothing -- last failed
(Just f,Just l) -> Just (f ++ l) -- both parts passed
I would like the result to be able to distinguish if the call fails for fst or snd. Short-circuiting the case of both failing to fst fail.
Use Either. It is basically the same as Maybe with a parameterised Nothing constructor, or in other words, Maybe a is isomorphic to Either () a. By replacing the () “unit error” with a custom error-tag type, you can make different failure cases different.
pulOh :: Seq -> Int -> Either String Seq
pulOh xs n = case tlTrn *** hdTrn $ splSq xs n of
(Nothing, _) -> Left "first failed"
(_, Nothing) -> Left "last failed"
(Just f,Just l) -> Right $ f ++ l
(I took the liberty of replacing that lambda with a *** “parallel pipeline”)
I was reading https://wiki.haskell.org/Do_notation_considered_harmful and was surprised to read the following lines
Newcomers might think that the order of statements determines the order of execution. ... The order of statements is also not the criterion for the evaluation order.
The wiki post gave some examples that demonstrate this property. While the examples make sense, I still don't fully believe that the statement is true, since if I write something like
main = do
putStrLn "foo"
putStrLn "bar"
putStrLn "baz"
The three lines come out in the order of the statements. So what exactly is going on here?
What it says is that the order of statements doesn't influence the evaluation criteria. As #chi points out in IO monad effects are sequenced in order but their evaluation order is still not known. An example of a monad which will make the concept clear:
test = do
x <- Just (2 + undefined)
y <- Nothing
return (x + y)
In ghci:
λ> test
Nothing
The above code has three statements. It can be de-sugared into the following form:
Just (2 + undefined) >>= \x -> Nothing >>= \y -> return (x + y)
Now since (>>=) is left associative, it will be evaluated like this:
(Just (2 + undefined) >>= \x -> Nothing) >>= \y -> return (x + y)
Note that Maybe monad is defined like this:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing -- A failed computation returns Nothing
(Just x) >>= f = f x -- Applies function f to value x
Applying the value (2 + undefined) to the function \x -> Nothing will result in Nothing.
The expression 2 + undefined is unevaluated, thanks to lazy evaluation strategy followed by Haskell.
Now we have a reduced form:
Nothing >>= \y -> return (2 + undefined + y)
Looking at the Monad instance for it, you can see that this will produce Nothing because Nothing >>= _ = Nothing.
What if the argument was strict instead:
test = do
!x <- Just (2 + undefined)
y <- Nothing
return (y + x)
Demo in ghci:
λ> test
*** Exception: Prelude.undefined
If we follows strict evaluation procedure, then you can see that order actually matters. But in a lazy setting, the order of statements doesn't matter. And hence the wiki claims, "the order of statements is not the criterion for the evaluation order".
So I defined a 'match' function as follows
let match :: Eq a => a -> [a] -> [Int]; match x = map (fromEnum . (==x))
Now I'm trying to define a new 'countN' function that counts the matches. When I try
let countN :: a -> [a] -> Int; countN x xs = ? $ match x xs
I get errors of the form: 'parse error of input '?''
You're getting an error because the compiler is parsing ? as an operator, and it sees two operators in a row, the second being $, which is illegal syntax. It looks like you copy/pasted this from somewhere that had the ? there as something to fill in, what do you think goes there?
EDIT:
To elaborate, what would you make of an expression like
myFunc x = + * ++ / x
To humans and any Haskell compiler, this expression makes no sense. What do all of those operators mean there? It can't be composition, the types wouldn't line up, and there just aren't enough arguments. This is the sort of problem the compiler has when it sees ? $ match x xs.
emptyAndOther
:: IO (Int, Int)
emptyAndOther =
do
c <- getChar
if c == '\ESC'
then return (x, y)
else if isSpace c
then (x+1) y
else x (y+1)
where
x = 0
y = 0
What is wrong with this code?
I want to count every empty line and every char and on ESC button, return the result.
Dont seem to understand, what is wrong
yes, i must use this signature
The problem lies in the fact that your else branches are attempting to call x as a function, which is a weird thing to do, since it's a number instead. I suggest trying to write a helper function
emptyAndOther' :: Int -> Int -> IO (Int, Int)
such that emptyAndOther = emptyAndOther' 0 0. For the future, I would point out that carefully reading error messages helps a lot. For example, GHC's error message says almost exactly what I did (though in terser language):
The function `x + 1' is applied to one argument,
but its type `Int' has none
In the expression: (x + 1) y
Here's a question in response. In the code:
else if isSpace c
then (x+1) y
else x (y+1)
What do the expressions (x+1) y and x (y+1) mean? I'm guessing you're trying to increment x and y, but haskell doesn't work that way.
Instead, try having emptyAndOther take the current value of x and y, and then recurse in those two cases by calling emptyAndOther (x+1) y or emptyAndOther x (y+1).
Your function has return type IO (Int,Int)
Now lets see the 3 branches in if/else
If part results in return (x, y) which is good as this will return a IO (Int,Int) and thats what your function return type is
Now in the else if and else part, the result seems to doesn't imply with the fact that your function return type is IO (Int,Int) .
Both the else if and else expressions should result in IO (Int,Int) type. This is just a hint. If you have worked in other programming language like C# and Java and try to write a function which return a string but in if part you return string and in else part you return int. That won't work .. same problem applies here
So I have the following function:
chk2 :: [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
chk2 i#((n,_):_)
| chkp (prod $ lgst i)==True = Right $ lgst i
| lgst i==i!!0 = Left $ chk2 $ (4-2,4-2):next i
| otherwise = Left $ chk2 $ next i
where prod (a,b) = a*b
lgst = foldl1 (\(a,b) (c,d) -> if prod (a,b) > prod (c,d) then (a,b) else (c,d))
next t = map (\(a,b) -> if (a,b)==lgst t then (a-1,b+1) else (a,b)) t
along with this error:
runhugs: Error occurred
ERROR "4/4.hs":14 - Type error in explicitly typed binding
*** Term : chk2
*** Type : [(Integer,Integer)] -> Either (Either [(Integer,Integer (Integer,Integer)) (Integer,Integer)
*** Does not match : [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
I'm trying to get this function to either end up with an (a,b) i.e. first guard or [(a,b)] i.e. the latter two guards. The basic problem is in the latter two guards.. if I take out the recursion, everything works fine, but I'm not sure how to define the type signature when returning the function itself.
The problem is with how you recurse.
According to the type of chk2, chk2 $ next i is of type Either [(Integer,Integer)] (Integer,Integer). Left is of type b -> Either b a, so Left $ chk2 $ next i is of type Either (Either [(Integer,Integer)] (Integer,Integer)) a for some unspecified type a.
Left $ chk2 $ (4-2,4-2):next i has a similar problem.
To fix, you need to decide how you want to handle the recursive value.
Easy fix:
| lgst i==i!!0 = chk2 $ (4-2,4-2):next i
| otherwise = chk2 $ next i
However, I doubt this is what you want, since it means all your results will be Right.
I'm not sure how to do what you want, because I'm not sure what you want.
What does a list result mean? What does a non-list result mean?
What you probably want to do is pattern match the result of the recursion, transforming Right pair -> Left [pair], perhaps appending some other result to the front.
As an example, I'll construct a recursive function with a similar type signature. Let foo be a function that takes a list of integers, and:
if the first element of the list is the maximum of the whole list, returns that element
otherwise, return a subsequence of the list, where each is the maximum of all the elements between it and the next element in the subsequence (or the end)
To do this:
foo :: [Integer] -> Either [Integer] Integer
foo [] = Left []
foo (x:xs) = case foo xs of
Left ys -> if all (<=x) ys
then Right x
else let (_,ys') = break (>x) ys in Left (x:ys')
Right y -> if x >= y
then Right x
else Left [x,y]
Note how I use case to pattern match on the result of the recursive call to foo.
To solve Euler #4, yours seems to be a very awkward style for Haskell. It's usually a bad idea to try and "port" code from other languages into Haskell, since the paradigm for Haskell is so very different.
You'll find a very clean, sensible solution to Euler #4 that uses list comprehensions at the Haskell Wiki. Certainly not the only solution, but it is at least 20x as readable as your current code. No offense.
I (and tons of other Haskellers) highly recommend Learn You a Haskell and Real World Haskell for learning how to approach problems the Haskell way, which in my experience is usually to create small, simple helper methods and compose them into a solution.