haskell : How to report an error for my function - haskell

this is an expansion to my last question here: basic haskell : Copying elements
however when an invalid input is added then I want it to print out an error message saying "negative value" or something similar. Is this possible in haskell?
working code:
copy :: Int->a->[a]
copy 0 _ = []
copy y a = [a]++(copy (y-1) a)
final line:
copy b c = error "negative value"

Because partial functions make me sad, I'd suggest doing something more along the lines of
copy :: Int -> a -> Maybe [a]
copy 0 _ = Just []
copy n a | n < 0 = Nothing
| otherwise = fmap (a:) (copy (n-1) a)
We've swapped out that if for a "guard"
foo bar | baz = quux
| ...
is just
foo bar = if baz then quux else ...
Note that I also changed your code a little,
[a] ++ copy (y-1) a ====> fmap (a:) (copy (y-1) a)
You can think of (:) as append.
1 : [2, 3] ==> [1, 2, 3]
It's the preferred alternative to [1] ++ [2, 3]. Say it out loud as "cons", like "construct". We can write this with an operator section
(a:) ==> \x -> a : x
Next we use this wonky fmap function. Think of fmap like this
fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)
So it unwraps a Just and applies a function before rewrapping the result. So our final code returns Nothing if our number is negative, otherwise, just the list.
Why aren't I recommending error? Well because error will blow up your whole program with pretty minimal information and it's a bad idea to try to catch it. Haskell doesn't even mandate that it's possible to do so, GHC just implements error in such a way that it's possible. In other words, you have little chance to recover.
This isn't a big deal for 10 lines of code, but I've spent upwards of 6 hours searching for the offending call to a function using error. It's much faster to debug and more idiomatic haskell.

You can do this with guards
copy :: Int -> a -> [a]
copy n x
| n < 0 = error "negative value"
| n == 0 = []
| otherwise = x : copy (n - 1) x
However, if this fails then it will likely crash your program. A better way is to use the Maybe type:
copySafe :: Int -> a -> Maybe [a]
copySafe n x
| n < 0 = Nothing
| otherwise = Just (copy n x)
Then you can use it as
main = do
putStrLn "Enter a number:"
nStr <- getLine
let n = read nStr :: Int
maybeXs = copySafe n n
case maybeXs of
Nothing -> putStrLn "You entered a negative number!"
Just xs -> print xs
This style forces you to consider both cases of copySafe, either it can fail on a negative value or it can return a valid list. It doesn't crash your program and the error handling is enforced by the type system.

look at http://www.haskell.org/haskellwiki/Error_vs._Exception
for example
copy b c = if c > b then error "negativ value"

Related

Recursive Haskell Function to Determine Position of Element in List

I have this code that will return the index of a char in a char array but I want my function to return something like -1 if the value isn't in the array. As it stands the function returns the size of the array if the element isn't in the array. Any ideas on how to change my code in order to apply this feature?
I am trying not to use any fancy functions to do this. I just want simple code without built-in functions.
isPartOf :: [(Char)] -> (Char) -> Int
isPartOf [] a = 0
isPartOf (a:b) c
| a == c = 0
| otherwise = 1 + isPartOf b c
For example:
*Main> isPartOf [('a'),('b'),('c')] ('z')
3
But I want:
*Main> isPartOf [('a'),('b'),('c')] ('z')
-1
Let's try to define such a function, but instead of returning -1 in case of element being not a part of the list, we can return Nothing:
isPartOf :: Eq a => [a] -> a -> Maybe Int
isPartOf [] _ = Nothing
isPartOf (x : xs) a | x == a = Just 0
| otherwise = fmap ((+) 1) (isPartOf xs a)
So, it works like that:
>> isPartOf [('a'),('b'),('c')] ('z')
Nothing
it :: Maybe Int
>> isPartOf [('a'),('b'),('c')] ('c')
Just 2
it :: Maybe Int
After that we can use built-in function fromMaybe to convert the Nothing case to -1:
>> fromMaybe (-1) $ isPartOf [('a'),('b'),('c')] ('c')
2
it :: Int
>> fromMaybe (-1) $ isPartOf [('a'),('b'),('c')] ('z')
-1
it :: Int
In case you're curios if such a function already exist, you can use Hoogle for that, searching the [a] -> a -> Maybe Int function: https://www.haskell.org/hoogle/?hoogle=%5Ba%5D+-%3E+a+-%3E+Maybe+Int
And the first answer will be elemIndex:
>> elemIndex 'c' [('a'),('b'),('c')]
Just 2
it :: Maybe Int
>> elemIndex 'z' [('a'),('b'),('c')]
Nothing
it :: Maybe Int
Hope this helps.
The smallest change to achieve this is
isPartOf :: [Char] -> Char -> Int
isPartOf [] a = (-1) -- was: 0
isPartOf (a:b) c
| a == c = 0
| otherwise = 1 + -- was: isPartOf b c
if (isPartOf b c) < 0 then (-2) else (isPartOf b c)
This is terrible computationally though. It recalculates the same value twice; what's worse is that the calculation is done with the recursive call and so the recursive call will be done twice and the time complexity overall will change from linear to exponential!
Let's not do that. But also, what's so special about Char? There's lots of stuff special about the Char but none are used here, except the comparison, (==).
The types the values of which can be compared by equality are known as those belonging to the Eq (for "equality") type class: Eq a => a. a is a type variable capable of assuming any type whatsoever; but here it is constrained to be such that ... yes, belongs to the Eq type class.
And so we write
isPartOf :: Eq a => [a] -> a -> Int
isPartOf [] a = (-1)
isPartOf (a:b) c
| a == c = 0
| otherwise = let d = isPartOf b c in
1 + if d < 0 then (-2) else d
That (-2) looks terribly ad-hoc! A more compact and idiomatic version using guards will also allow us to address this:
isPartOf :: Eq a => [a] -> a -> Int
isPartOf [] a = (-1)
isPartOf (a:b) c
| a == c = 0
| d < 0 = d
| otherwise = 1 + d
where
d = isPartOf b c
Yes, we can define d in the where clause, and use it in our guards, as well as in the body of each clause. Thanks to laziness it won't even be calculated once if its value wasn't needed, like in the first clause.
Now this code is passable.
The conditional passing and transformation is captured by the Maybe data type's Functor interface / instance:
fmap f Nothing = Nothing -- is not changed
fmap f (Just x) = Just (f x) -- is changed
which is what the other answer here is using. But it could be seen as "fancy" when we only start learning Haskell.
When you've written more functions like that, and become "fed up" with repeating the same pattern manually over and over, you'll come to appreciate it and will want to use it. But only then.
Yet another concern is that our code calculates its result on the way back from the recursion's base case.
But it could instead calculate it on the way forward, towards it, so it can return it immediately when the matching character is found. And if the end of list is found, discard the result calculated so far, and return (-1) instead. This is the approach taken by the second answer.
Though creating an additional function litters the global name space. It is usual to do this by defining it internally, in the so called "worker/wrapper" transformation:
isPartOf :: Eq a => [a] -> a -> Int
isPartOf xs c = go xs 0
where
go [] i = (-1)
go (a:b) i
| a == c = i
| otherwise = -- go b (1 + i)
go b $! (1 + i)
Additional boon is that we don't need to pass around the unchanged value c -- it is available in the outer scope, from the point of view of the internal "worker" function go, "wrapped" by and accessible only to our function, isPartOf.
$! is a special call operator which ensures that its argument value is calculated right away, and not delayed. This eliminates an unwanted (in this case) laziness and improves the code efficiency even more.
But from the point of view of overall cleanliness of the design it is better to return the index i wrapped in a Maybe (i.e. Just i or Nothing) instead of using a "special" value which is not so special after all -- it is still an Int.
It is good to have types reflect our intentions, and Maybe Int expresses it clearly and cleanly, so we don't have to remember which of the values are special and which regular, so that that knowledge is not external to our program text, but inherent to it.
It is a small and easy change, combining the best parts from the two previous variants:
isPartOf :: Eq a => [a] -> a -> Maybe Int
isPartOf .....
.......
....... Nothing .....
.......
....... Just i .....
.......
(none of the code was tested. if there are errors, you're invited to find them and correct them, and validate it by testing).
You can achieve it easily if you just pass current element idx to the next recursion:
isPartOf :: [Char] -> Char -> Int
isPartOf lst c = isPartOf' lst c 0
isPartOf' :: [Char] -> Char -> Int -> Int
isPartOf' [] a _ = -1
isPartOf' (a:b) c idx
| a == c = idx
| otherwise = isPartOf' b c (idx + 1)
You are using your function as an accumulator. This is cool except the additions with negative one. An accumulator cannot switch from accumulating to providing a negative 1. You want two different things from your function accumulator. You can use a counter for one thing then if the count becomes unnecessary because no match is found and a negative 1 is issued and nothing is lost. The count would be yet another parameter. ugh. You can use Maybe but that complicates. Two functions, like above is simpler. Here are two functions. The first is yours but the accumulator is not additive it's concatenative.
cIn (x:xs) c | x == c = [1]
| null xs = [-1]
| otherwise = 1:cIn xs c
Cin ['a','b','c'] 'c'
[1,1,1]
cIn ['a','b','c'] 'x'
[1,1,-1]
So the second function is
f ls = if last ls == 1 then sum ls else -1
It will
f $ Cin ['a','b','c'] 'c'
3
and
f $ Cin ['a','b','c'] 'x'
-1
You can zero the index base by changing [1] to [0]

Haskell: Exception <<loop>> on recursive data entry

So I'm trying to make a little program that can take in data captured during an experiment, and for the most part I think I've figured out how to recursively take in data until the user signals there is no more, however upon termination of data taking haskell throws Exception: <<loop>> and I can't really figure out why. Here's the code:
readData :: (Num a, Read a) => [Point a] -> IO [Point a]
readData l = do putStr "Enter Point (x,y,<e>) or (d)one: "
entered <- getLine
if (entered == "d" || entered == "done")
then return l
else do let l = addPoint l entered
nl <- readData l
return nl
addPoint :: (Num a, Read a) => [Point a] -> String -> [Point a]
addPoint l s = l ++ [Point (dataList !! 0) (dataList !! 1) (dataList !! 2)]
where dataList = (map read $ checkInputData . splitOn "," $ s) :: (Read a) => [a]
checkInputData :: [String] -> [String]
checkInputData xs
| length xs < 2 = ["0","0","0"]
| length xs < 3 = (xs ++ ["0"])
| length xs == 3 = xs
| length xs > 3 = ["0","0","0"]
As far as I can tell, the exception is indication that there is an infinite loop somewhere, but I can't figure out why this is occurring. As far as I can tell when "done" is entered the current level should simply return l, the list it's given, which should then cascade up the previous iterations of the function.
Thanks for any help. (And yes, checkInputData will have proper error handling once I figure out how to do that.)
<<loop>> basically means GHC has detected an infinite loop caused by a value which depends immediately on itself (cf. this question, or this one for further technical details if you are curious). In this case, that is triggered by:
else do let l = addPoint l entered
This definition, which shadows the l you passed as an argument, defines l in terms of itself. You meant to write something like...
else do let l' = addPoint l entered
... which defines a new value, l', in terms of the original l.
As Carl points out, turning on -Wall (e.g. by passing it to GHC at the command line, or with :set -Wall in GHCi) would make GHC warn you about the shadowing:
<interactive>:171:33: warning: [-Wname-shadowing]
This binding for ‘l’ shadows the existing binding
bound at <interactive>:167:10
Also, as hightlighted by dfeuer, the whole do-block in the else branch can be replaced by:
readData (addPoint l entered)
As an unrelated suggestion, in this case it is a good idea to replace your uses of length and (!!) with pattern matching. For instance, checkInputData can be written as:
checkInputData :: [String] -> [String]
checkInputData xs = case xs of
[_,_] -> xs ++ ["0"]
[_,_,_] -> xs
_ -> ["0","0","0"]
addPoint, in its turn, might become:
addPoint :: (Num a, Read a) => [Point a] -> String -> [Point a]
addPoint l s = l ++ [Point x y z]
where [x,y,z] = (map read $ checkInputData . splitOn "," $ s) :: (Read a) => [a]
That becomes even neater if you change checkInputData so that it returns a (String, String, String) triple, which would better express the invariant that you are reading exactly three values.

Recursively dropping elements from list in Haskell

Right now I'm working on a problem in Haskell in which I'm trying to check a list for a particular pair of values and return True/False depending on whether they are present in said list. The question goes as follows:
Define a function called after which takes a list of integers and two integers as parameters. after numbers num1 num2 should return true if num1 occurs in the list and num2 occurs after num1. If not it must return false.
My plan is to check the head of the list for num1 and drop it, then recursively go through until I 'hit' it. Then, I'll take the head of the tail and check that against num2 until I hit or reach the end of the list.
I've gotten stuck pretty early, as this is what I have so far:
after :: [Int] -> Int -> Int -> Bool
after x y z
| y /= head x = after (drop 1 x) y z
However when I try to run something such as after [1,4,2,6,5] 4 5 I get a format error. I'm really not sure how to properly word the line such that haskell will understand what I'm telling it to do.
Any help is greatly appreciated! Thanks :)
Edit 1: This is the error in question:
Program error: pattern match failure: after [3,Num_fromInt instNum_v30 4] 3 (Num_fromInt instNum_v30 2)
Try something like this:
after :: [Int] -> Int -> Int -> Bool
after (n:ns) a b | n == a = ns `elem` b
| otherwise = after ns a b
after _ _ _ = False
Basically, the function steps through the list, element by element. If at any point it encounters a (the first number), then it checks to see if b is in the remainder of the list. If it is, it returns True, otherwise it returns False. Also, if it hits the end of the list without ever seeing a, it returns False.
after :: Eq a => [a] -> a -> a -> Bool
after ns a b =
case dropWhile (/= a) ns of
[] -> False
_:xs -> b `elem` xs
http://hackage.haskell.org/package/base-4.8.2.0/docs/src/GHC.List.html#dropWhile
after xs p1 p2 = [p1, p2] `isSubsequenceOf` xs
So how can we define that? Fill in the blanks below!
isSubsequenceOf :: Eq a => [a] -> [a] -> Bool
[] `isSubsequenceOf` _ = ?
(_ : _) `isSubsequenceOf` [] = ?
xss#(x : xs) `isSubsequenceOf` (y:ys)
| x == y = ?
| otherwise = ?
after :: [Int] -> Int -> Int -> Bool
Prelude> let after xs a b = elem b . tail $ dropWhile (/=a) xs
Examples:
Prelude> after [1,2,3,4,3] 88 7
*** Exception: Prelude.tail: empty list
It raises an exception because of tail. It's easy to write tail' such that it won't raise that exception. Otherwise it works pretty well.
Prelude> after [1,2,3,4,3] 2 7
False
Prelude> after [1,2,3,4,3] 2 4
True

Haskell Continuation passing style index of element in list

There's a series of examples I'm trying to do to practice Haskell. I'm currently learning about continuation passing, but I'm a bit confused as to how to implement a function like find index of element in list that works like this:
index 3 [1,2,3] id = 2
Examples like factorial made sense since there wasn't really any processing of the data other than multiplication, but in the case of the index function, I need to compare the element I'm looking at with the element I'm looking for, and I just can't seem to figure out how to do that with the function parameter.
Any help would be great.
first let me show you a possible implementation:
index :: Eq a => a -> [a] -> (Int -> Int) -> Int
index _ [] _ = error "not found"
index x (x':xs) cont
| x == x' = cont 0
| otherwise = index x xs (\ind -> cont $ ind + 1)
if you prefer point-free style:
index :: Eq a => a -> [a] -> (Int -> Int) -> Int
index _ [] _ = error "not found"
index x (x':xs) cont
| x == x' = cont 0
| otherwise = index x xs (cont . (+1))
how it works
The trick is to use the continuations to count up the indices - those continuations will get the index to the right and just increment it.
As you see this will cause an error if it cannot find the element.
examples:
λ> index 1 [1,2,3] id
0
λ> index 2 [1,2,3] id
1
λ> index 3 [1,2,3] id
2
λ> index 4 [1,2,3] id
*** Exception: not found
how I figured it out
A good way to figure out stuff like this is by first writing down the recursive call with the continuation:
useCont a (x:xs) cont = useCont a xs (\valFromXs -> cont $ ??)
And now you have to think about what you want valFromXs to be (as a type and as a value) - but remember your typical start (as here) will be to make the first continuation id, so the type can only be Int -> Int. So it should be clear that we are talking about of index-transformation here. As useCont will only know about the tail xs in the next call it seems natural to see this index as relative to xs and from here the rest should follow rather quickly.
IMO this is just another instance of
Let the types guide you Luke
;)
remarks
I don't think that this is a typical use of continuations in Haskell.
For once you can use an accumulator argument for this as well (which is conceptional simpler):
index :: Eq a => a -> [a] -> Int -> Int
index _ [] _ = error "not found"
index x (x':xs) ind
| x == x' = ind
| otherwise = index x xs (ind+1)
or (see List.elemIndex) you can use Haskells laziness/list-comprehensions to make it look even nicer:
index :: Eq a => a -> [a] -> Int
index x xs = head [ i | (x',i) <- zip xs [0..], x'== x ]
If you have a value a then to convert it to CPS style you replace it with something like (a -> r) -> r for some unspecified r. In your case, the base function is index :: Eq a => a -> [a] -> Maybe Int and so the CPS form is
index :: Eq a => a -> [a] -> (Maybe Int -> r) -> r
or even
index :: Eq a => a -> [a] -> (Int -> r) -> r -> r
Let's implement the latter.
index x as success failure =
Notably, there are two continuations, one for the successful result and one for a failing one. We'll apply them as necessary and induct on the structure of the list just like usual. First, clearly, if the as list is empty then this is a failure
case as of
[] -> failure
(a:as') -> ...
In the success case, we're, as normal, interested in whether x == a. When it is true we pass the success continuation the index 0, since, after all, we found a match at the 0th index of our input list.
case as of
...
(a:as') | x == a -> success 0
| otherwise -> ...
So what happens when we don't yet have a match? If we were to pass the success continuation in unchanged then it would, assuming a match is found, eventually be called with 0 as an argument. This loses information about the fact that we've attempted to call it once already, though. We can rectify that by modifying the continuation
case as of
...
(a:as') ...
| otherwise -> index x as' (fun idx -> success (idx + 1)) failure
Another way to think about it is that we have the collect "post" actions in the continuation since ultimately the result of the computation will pass through that code
-- looking for the value 5, we begin by recursing
1 :
2 :
3 :
4 :
5 : _ -- match at index 0; push it through the continuation
0 -- lines from here down live in the continuation
+1
+1
+1
+1
This might be even more clear if we write the recursive branch in pointfree style
| otherwise -> index x as' (success . (+1)) failure
which shows how we're modifying the continuation to include one more increment for each recursive call. All together the code is
index :: Eq a => a -> [a] -> (Int -> r) -> r -> r
index x as success failure
case as of
[] -> failure
(a:as') | x == a -> success 0
| otherwise -> index x as' (success . (+1)) failure

Haskell: writing the result of a computation to file

I have a function which creates a tuple after computation, but I would like to write it to file.
I know how to write to a file using writeFile, but do not know how to combine the computation and monads IO together in the type signature.
This is my code.
invest :: ([Char]->Int->Int->([Char], Int) )
-> [Char]->Int->Int->([Char], Int)
invest myinvest x y = myinvest x y
myinvest :: [Char]->Int->Int->([Char], Int)
myinvest w x y
| y > 0 = (w, x + y)
| otherwise = error "Invest amount must greater than zero"
where
I have a function which computes the maximum value from a list, but I want this function to receive input from a file, and then perform the computation of maximum value.
maximuminvest :: (Ord a) => [a] -> a
maximuminvest [] = error "Empty Invest Amount List"
maximuminvest [x] = x
maximuminvest (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximuminvest xs
Please help.
Thanks.
[Edit]
My new question is at below.
The first and second question can be solve through function composition but when i try it say type mismatch.
I have check it but i couldn't find any errors.
invest :: ( [Char]->Int->Int->([Char], Int) ) -> [Char]->Int->Int-> ([Char], Int)
invest theinvest x y = theinvest x y
theinvest :: [Char]->Int->Int-> ([Char], Int)
theinvest w x y | y > 0 = (w, x + y)
| otherwise = error "Invest amount must greater than zero"
savefile :: ([Char], Int) -> IO()
savefile (x, y) = do
let name = fst (x, y)
let temp = snd(x, y)
let amount = show temp
writeFile "C:\\Invest.txt" (name ++ " " ++ amount)
test = savefile . theinvest "asd" 1234 234
The error message is
ERROR - Type error in application
* Expression : savefile . invest theinvest "234" 234 234
Term : invest theinvest "234" 234 234
Type : ([Char],Int)
* Does not match : a -> b
Please help. My return type is ([Char],Int). Why it complaint as a -> b ? Thanks
I solve this using command like savefile (invest theinvest "asd" 12 12) but why the operator doesn;t works ?
My fourth question is i have something like this ["peter","1000","michell","2000","kelly","3000"] and i would like to convert to [("peter",1000),("michell", 2000),("kelly",3000)]
The reading of file content is ok but i want to filter the string and get the number only. For instance, a file that has "peter 100\nasd 200"
I would like to drop the alphabet and remain the integer here.
I just want the [100, 200] to be the argument the function.
Please help.
Thanks.
You might want to do something like
main = do
c <- computation
writeFile "filename" (show c)
to write out to the file using a Show instance for the result of the computation. If your types are easy enough, this is both human-readable and readable for Haskell restoring the value again.
For the second question, suppose your file stores values as
[1.5,2.3,5.1,6.3,9.8]
then it is blindingly easy to read them in and perform a computation:
main = do
str <- readFile "filename"
return $ computation (read str)
should do it. If instead you have your data with an item per line, or in a CSV file, or something else, it gets a little bit more involved. For CSV there is Text.CSV up on Hackage that seems to do the trick.
For your question about funcion composition, you have to remember that function application binds very strongly - more strongly than composition. So your problematic expression parses as
savefile . (theinvest "asd" 1234 234)
The type of (theinvest "asd" 1234 234) is ([Char],Int) which is not a function and can't be composed. That's what the type error is about.
You want to apply savefile to this, and the easiest is to just remove the . and put the parentheses in. Another way is to replace the . by $ which is a weakly binding function application operator. And if you really, really want a period in there, you could use (savefile . theinvest "asd" 1234) 234 but that's very silly and unclear, in my opinion.
creates a tuple after computation, but I would like to write it to file.
The simplest way is with 'show', which gives a text-based serialization method for most Haskell data types.
writeFile "foo" (show c)
For more efficient serialization, there is Data.Binary:
encodeFile "foo" c
Which will write it in a binary format.
for your last question you would use lines to get ["peter 2000", Joe "50"] etc. then use filter to drop non numerics.
so
filter Data.Char.isDigit . lines
should do it(Note: code written without being tested may not be 100%, and it doesn't handle the case of "7Bill 400" correctly.)

Resources