Im getting started to Haskell, and im trying to define the factorial function that takes one number and, if the number is negative, show nothing as result. Like this (just an example):
*Main> factorial 8
40320
*Main> factorial (-1)
*Main>
Is it possible, and how?
Thanks.
You can't do this with just a function, and it's probably not what you want anyhow. A function always has to return something, even if it's just a dummy value that represents not having a valid result! This is useful because it means the result of your function can always be used by other parts of your program—everything is more composable.
The usual idiomatic solution is to use the Maybe type, which lets you return either Just the result or Nothing:
factorial n | n < 0 = Nothing
| n < 2 = Just 1
| otherwise = ...
If you really want your behavior in GHCi, you can print out the result you want instead of returning it directly. This gives you more control over how the output looks, but it means you won't be able to reuse the result of your function directly. You can do it like this:
factorialPrint n | n < 0 = return () -- an IO action that does nothing
| otherwise = print (factorial n)
Instead of producing a result, this function produces an IO action. GHCi then executes this action and doesn't print anything itself, which means you have to print the result yourself explicitly.
If you want to keep it pure then you can do it by defining a new result type and defining show to convert to an empty string if the result is invalid:
data FactResult = R Integer | Invalid
instance Show FactResult where
show (R i) = show i
show Invalid = ""
factorial n | n < 0 = Invalid
factorial n = R $ product [1..n]
The "correct" way to do something like this would be to use Maybe.
factorial n
| n < 0 = Nothing
| n == 1 = Just 1
| otherwise = fmap (*n) $ factorial (n-1)
This outputs "Just n!" with an input of anything >= 0 and "Nothing" otherwise.
If you really want a blank response.
maybeStr Nothing = ""
maybeStr (Just x) = show x
Then to run print it you would say:
f = putStrLn . maybeStr . factorial
f 4 -- would print 24
f (-1) -- would print blank line
Yes this is possible, but we have to slightly change the factorial function:
fac :: Int -> IO ()
fac n
| n < 0 = return ()
| otherwise = print $ facHelp n
where
facHelp n = <your factorial function>
Now, in addition to the standard factorial, we check the input first and if the input is smaller than 0, we just return a thing called unit, which is nothing (to see at least). If the input is valid for the factorial, we will just print it normally.
Related
I am new to Haskell and trying few things. I have a small program.
module Collatz where
compute_collatz :: Integer -> Integer
compute_collatz x = if even x then evenComputation else oddcomputation
where evenComputation = div x 2
oddcomputation = 3 * x + 1
compute_steps :: Integer -> Integer
compute_steps 1 = 0
compute_steps num = 1 + compute_steps(compute_collatz(num))
I wanted to print the sequence of numbers generated by each compute_collatz(num) call. How can I add a print or show statement in either compute_steps or compute_collatz functions
This is not a good approach.
A better alternative is to make the result of the function a list of visited numbers, instead of just the final one.
collatzSeq :: Integer -> [Integer]
collatzSeq 1 = [1]
collatzSeq x
| even x = x : collatzSeq (x`div`2)
| otherwise = x : collatzSeq (3*x + 1)
Then you can use this list for counting steps, printing, whatever. Note that thanks to lazyness you need need to worry that the whole list would need to be computed before the printing starts – it'll just print as you go in the computation.
First of all, I want to say that I'm very very inexperienced with Haskell, and I know that I have done something (or multiple things) terribly wrong, been struggling for hours but I can't seem to find it.
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
list = replicate y x
foldr (*) x list
main = print $ power 3 5
Error most of the time is either x and y not being passed to the replicate function or that foldr is a naked function, I understand what they both mean but have no idea on how I can pass the variables or come up with a solution.
You here created four functions: power, list, foldr and main. But you use variables x and y in the definition of the list function.
You can work with a where clause to specify subexpressions, for example:
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) 1 list
where list = replicate y x
or perhaps more elegant with pattern matching:
power :: Int -> Int -> Int
power 0 _ = 0
power x y = foldr (*) 1 (replicate y x)
main = print $ power 3 5
Here we can also eliminate the case for x0, since our foldr starts working with 1, not x.
This algorithm is however not very efficient, since it is linear in the value of y. By checking recursively if the exponent is even or odd, you can make it faster. I leave this as an exercise.
You were very close! The main things that need to be fixed are:
When writing a definition with guards, the “fallback” case needs to be a guard as well, conventionally written with otherwise.
Recall that a definition without guards looks like this, with one left side (a name and parameter patterns/names) and one right side (an expression):
name patterns = expression
With guard conditions, there is one right-hand side for each guard:
name patterns | condition1 = expression1
| condition2 = expression2
…
| otherwise = expressionn
otherwise is really just an alias for True, that is, such a guard always matches. The only thing special about otherwise is that the compiler uses it as a hint when analysing whether a pattern match covers all possible cases.
In order to define a variable list, local to the definition of power, using the parameters x and y, you need to use either a let…in… expression, that is, let block in expression, or a where clause, equation where block. A block is a series of items (in this case, local definitions) which must all be written starting at the same column of indentation, or be delimited by explicit curly braces {…} and semicolons ;.
Using let…in… follows the structure of your original code pretty closely. I will adjust the indentation style to avoid needing to align anything, by putting a newline and a constant amount of indentation instead.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let
list = replicate y x
in foldr (*) x list
main :: IO ()
main = print $ power 3 5
Attaching a where clause to an equation is slightly more common than using a let…in… expression on the right side of an equation.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) x list
where
list = replicate y x
main :: IO ()
main = print $ power 3 5
Note that in this case, there is a slight difference: the variable list is visible in all of the right-hand sides, although we only use it in one of them. With let list = … in e, list is only defined within e. In general, it’s helpful for readability to keep the scope of a variable as small as possible, although you can certainly go overboard:
a = …
where
b = …
where
c = …
where
d = …
-- If you see this much nesting, rethink!
If you run into issues with alignment and indentation, you can always use explicit delimiters instead. The code I wrote is equivalent to the following.
power :: Int -> Int -> Int; -- Begin ‘power’ signature.
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let { -- Begin ‘let’ block.
list = replicate y x; -- End ‘list’ equation.
} in foldr (*) x list; -- End ‘let’ block, then end ‘power’ equation.
main :: IO (); -- Begin ‘main’ signature.
main = print $ power 3 5; -- End ‘main’ equation.
Or similarly with where { … }.
i just learned haskell yesterday and i'm stuck with a task.
i have a Matrix given; implemented with a function like this:
board 1 1 = 0
board 1 2 = 1
board 1 3 = 0
board 2 1 = 2
board 2 2 = 0
board 2 3 = 0
board 3 1 = 1
board 3 2 = 0
board 3 3 = 2
board _ _ = -1
Just that you have a little context:
that matrix is used for a minified sinking ships game.
so you would check an entry 2 1 like this
board 2 1
and get the respective result.
0 is a default value, -1 doesnt exist; 1 stands for a ship owned by player 1, the same goes with 2.
Now i have to write a function that just has to count the amount of ships owned by a specific player and it should return that amount.
e.g in that example board, the amount of 2's would be 2.
However, i have a restriction that i cant use anything related to lists.
I guess i have to work with recursion, and this is where i'm stuck.
i already have made a try with this:
(k is the player number and res should be the result.)
amountofships k board = rekurs 1 1 board res
where
res = 0
rekurs x y board res =
if (board x y == -1) then return(res)
else return(rekurs (x + 1) 1 board res)
where
new_rekurs a b board res2 =
if (board a b == -1) then return(res2)
else if (board a b == k) then return(new_rekurs a (b+1) board (res + 1))
else return(new_rekurs a (b+1) board res)
where
res2 = 0
Its meant to have a resursion function that goes through every column and inside that, it has another recursion function that would check every entry inside that column, return the amount, then check the next column, etc.
it doesnt compile and i dont think its an elegant approach, but I cant think of another one.
I would be thankful for any kind of help.
Edit : Thank you all for your answers. I see where the problem in my Code was.
I've used the structure proposed by Daniel, and it compiles at least:
amountofships k board = rekursColumn 1 1 0
where
rekursColumn x y res
| board x y = res
| otherwise = rekursColumn (x + 1) y (res + rowTotal)
where
rowTotal = rekursRow x y 0
rekursRow x y res
| board x y = res
| otherwise = rekursRow x (y + 1) (res + isOurBoat)
where
isOurBoat = if board x y == k then 1 else 0
I still get an Could not deduce (Num Bool) arising from the literal ‘1’
Error when calling
amountofships 1 example_board
. I guess this is because i didnt specify what the input types are? Specially since one parameter is actually a function.
Edit2: Oh i see where the problem was. I need to check if board x y == -1
my Code is working now:
amountofships :: Int -> (Int -> Int -> Int) -> Int
amountofships k board = rekursColumn 1 1 0
where
rekursColumn x y res
| board x y == -1 = res
| otherwise = rekursColumn (x + 1) y (res + rowTotal)
where
rowTotal = rekursRow x y 0
rekursRow x y res
| board x y == -1 = res
| otherwise = rekursRow x (y + 1) (res + isOurBoat)
where
isOurBoat = if board x y == k then 1 else 0
Thank you all for your help!
Okay, yes, you're a bit confused.
So my advice first is to try to straighten out what you want to do, in mostly English. I'm going to try to lead you to that without outright giving you the answer, since the point of this exercise is for you to learn more Haskell.
So it seems to me - though you haven't explained it - that what you intend to happen is:
amountofships calls internal function rekurs telling it to start at position 1 1 and passing it an accumulator argument that should start at 0
rekurs should examine the spot it's given, and if that spot is -1 say "oh, I'm off the grid, return the accumulator argument", and otherwise it should return the result of calling itself with one spot to the right.
Then you also somewhere define something called new_rekurs that you don't ever call.
So first let's try to fix your logic first, and then if you still have trouble translating that into Haskell we can work on that.
So the general pattern that you seem to be following is "call an internal tail-recursive function with an accumulator argument that checks "am I done yet?" and, if done, returns the accumulator argument. If not done, it computes the next place it should go and then calls itself on that."
Now, that's an okay pattern to use to solve this, but there are two problems with what you're doing:
You never add anything to the accumulator.
You need to travel in two dimensions.
So, traveling in two dimensions: there are two ways to do it. One is to keep a single function that keeps increasing x with each step until it gets to -1 and then increases y by 1 and reset x to 1. Another way - which I think in your case will be much, much easier - is to have two functions called rekursBoard and rekursRow (or whatever names you prefer) and the first function calls the second one to get the number of relevant ships in each row.
With the two-function solution, what you'd want to do is:
At the top level, call rekursBoard 1 1 0 (the arguments there are x, y, and res - note that you don't need to keep passing the board function on down to the inner functions)
In rekursBoard check if the given spot is off the board. If it is, the result is just res. If not, then the result is rekursBoard (x+1) y (res+rowTotal), where rowTotal is computed by calling rekursRow x y 0.
In rekursRow, check if the given spot is off the board. If it is, the result is just res. Otherwise, the result is rekursRow x (y+1) (res+isOurBoat), where isOurBoat is computed as 1 if the boat at spot x and y matches the k the top-level function was given, and 0 if not.
The overall structure of your function could look like this:
amountofships k board = -- .... some call here
where
rekursBoard x y res = -- ... some stuff here
where
rowTotal = -- ... some call here
rekursRow x y res = -- ... some stuff here
where
isOurBoat = -- ... something here
This isn't the only way to structure it, of course, it's just what I would do if I were writing up the answer sheet to this problem. Another very viable way to structure it is to make rekursRow something that's defined inside the where clause of rekursBoard and doesn't an x argument.
Now, a word in general on working in Haskell - Haskell has a function called return that means almost nothing like you expect. Seriously, at this early stage of learning Haskell, don't use return unless you're copying boilerplate code from the book. return DOES NOT DO WHAT YOU EXPECT. I personally think that the function is poorly named and that modern Haskell courses should avoid ever putting return on the page and instead use pure every place where they use return. (since on modern Haskell compilers, return and pure are the same thing for all the standard Monads)
Therefore, if you put return in your Haskell code for this problem, you will be sorry.
Don't do it.
Instead, get used to writing code like this:
countEmptySquare x y board = if board x y == 0 then 1 else 0
That is, just the form if someExpression then onePossibility else otherPossibility. No return statement, just bare expressions.
This will seem tedious at first, breaking down each calculation into named pieces, but it gets better. However, for laying out what's going on at an early level you should work through the careful break down.
First let me clean up that code of yours, syntactically:
amountofships :: ... -- Always write out type signatures!
amountofships k board = rekurs 1 1 board res
where res = 0
rekurs x y board res
| board x y == -1 = return res -- guards usually read nicer than `if`
| otherwise = return $ rekurs (x + 1) 1 board res
where new_rekurs a b board res2
| board a b == -1 = return res2 -- no need for parens around function arguments!
| board a b == k = return $ new_rekurs a (b+1) board (res + 1)
| otherwise = return $ new_rekurs a (b+1) board res
where res2 = 0
Now, a big problem here is return. Note that return in Haskell is very different from return in most other languages. It is not a keyword that's generally needed for the result of functions, instead, return is itself just a library function:
return :: Monad m => a -> m a
You need this to inject a value of “pure type” a, for example 3 :: Int, into the result of a monadic action of type m a, e.g. Just 3 :: Maybe Int. For example, you might use it thus:
-- Find the first even number in the tuple, if any
fstEven :: (Int, Int) -> Maybe Int
fstEven (a,b)
| even a = return a -- for the `Maybe` monad, this is the
| even b = return b -- same as writing `Just a` / `Just b`.
| otherwise = Nothing
Observe that I didn't write return Nothing: that would wrap the already monadic, empty value Nothing :: Maybe Int into another monadic layer, which is too much monad here.
Similar in your code: you wrap every result in return, but never unwrap anything.
Since in your case, everything is “pure” anyway, there's simply no need for that. To make something the result of a function, just write it out, like:
-- Use the first number in the tuple, if it's even; else use the second.
fstIfEven :: (Int, Int) -> Int
fstIfEven (a,b)
| even a = a
| otherwise = b
Or, in your case,
amountofships :: ... -- Always write out type signatures!
amountofships k board = rekurs 1 1 board res
where res = 0
rekurs x y board res
| board x y == -1 = res
| otherwise = rekurs (x + 1) 1 board res
where new_rekurs a b board res2
| board a b == -1 = res2
| board a b == k = new_rekurs a (b+1) board (res + 1)
| otherwise = new_rekurs a (b+1) board res
where res2 = 0
That looks better, but it doesn't work – here comes the interesting problem. See, you seem to not really think of recursion here. For a “recursive loop” in Haskell, you don't initialise a variable with something like res = 0 and then somehow change it in the course of the loop. Rather you straight up call the loop-body function with the initial value as the “front-end argument”, and then keep the function calling itself with other arguments. I'll demonstrate it for the simplified problem with only one grid-dimension. Instead of these magic numbers, I shall use descriptive tag types:
data Player = PlayerA | PlayerB
deriving (Eq, Show)
data BoardField = Coast | OpenSea | Ship Player
deriving (Eq, Show)
type Board = Int -> BoardField -- “array” of fields which may have ships in them, starting with index 0
amountOfShips :: Player -> Board -> Int
amountOfShips k board = go 0 0 -- the `board` is always the same, no need to pass
-- it explicitly to the worker-loop function `go`
where go x res = case board x of -- `case` is even better than guards, if all you're doing is equality comparison.
Coast -> res -- When we've reached the coast we're done, there can be no more ships.
Ship player
| player==k -> go (x+1) (res+1) -- Found ship of the requested player,
-- therefore continue recursion with incremented accumulator
_ -> go (x+1) res -- No ships here, so continue recusion with the same accumulator.
I have been at this for a long time, I cant figure out whats wrong
Haskell just makes me feel so dumb
data Operation
= Nth Integer
fib :: (Integral i, Integral j) => i -> j
fib n | n == 0 = 1
| n == 1 = 1
| n == 2 = 1
| n == 3 = 1
| otherwise = (fib(n-1)+fib(n-2))* fib(n-3) `div` fib(n-4)
main = do
command <- getLine
case command of
Nth op -> show $ fib op
Nothing -> "Invalid operation"
So when the user inputs Nth 9, the fib function needs to get called with n=9 and give the output to the user. I feel like my case control structure is appropriate, but I cant get it to work at all!!!
you are almost complete.
use deriving (Read) for reading String as Operation.
http://en.wikibooks.org/wiki/Haskell/Classes_and_types#Deriving
If you want to handle read error, see How to catch a no parse exception from the read function in Haskell?
data Operation = Nth Integer deriving (Read)
fib :: (Integral i, Integral j) => i -> j
fib n | n == 0 = 1
| n == 1 = 1
| n == 2 = 1
| n == 3 = 1
| otherwise = (fib(n-1)+fib(n-2))* fib(n-3) `div` fib(n-4)
main = do
command <- getLine
print $ case read command of
Nth op -> fib op
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"