multiply :: Int -> Int -> Int
multiply a b = a * b
minus :: Int -> Int -> Int
minus a b = a - b
minus2 :: Int -> Int -> Int
minus2 a b = b – a
minus2 (multiply (minus 3 5) 7) 9
minus2 ((minus 3 5) * 7) 9
9 - ((minus 3 5) * 7)
9 - ((3 - 5) * 7)
9 - ((-2) * 7)
9 - (-14)
23
Running the line minus2 (multiply (minus 3 5) 7) 9
Do I have the correct order of evaluation that Haskell would use?
Still new with functional programming so I'm not sure if I have the "lazy evaluation" process correct.
You can test your hypothesis by replacing subexpressions by (error "x"), (error "y"), etc. Whichever error is evaluated first is the one to show up when you run the expression.
To the point, evaluation can proceed in any order the compiler wants it to, as long as it gets the correct answer. For example, it could optimize the entire expression to 23 and have no evaluation at all at runtime. It could evaluate the right side of arithmetic operators before the left side, except for subtraction. It could randomly decide at runtime which to evaluate first.
Ignoring that, for an explanation of how to manually do the work, see "How Lazy Evaluation Works in Haskell".
But how to manually figure it out is not the main point of this answer. Your question was what evaluation order Haskell would actually use, so this answer loosely intends to tell you the evaluation order your program uses when compiled with the compiler of your choice (ignoring some caveats that don't matter for basic understanding of evaluation order).
With some work, we can have Haskell tell us what order it evaluates in. If you're in school, you probably want to learn how to find the evaluation order manually without assistance so that you can do well on a test.
It's recommended that you only do this to check an answer you're confident in. You can also use it if you get stuck, but you should only read up until the point that you're stuck to see what the next step is and to make an educated guess about why that's the next step so that you can begin to learn what the rules are by experimenting. This, in combination with the above linked article, will help quite a bit.
To do this, we can expand upon Jonas Duregård's answer by using Debug.Trace's functions instead of error. Debug.Trace's functions can output things when something starts or stops being evaluated, so they're quite appropriate here:
import Debug.Trace
-- Show result
r :: String -> Int -> Int
r nm n = trace ("Result of " ++ nm ++ " is " ++ show n) n
-- Show evaluation of Int -> Int -> Int function
f :: String -> (Int -> Int -> Int) -> Int -> Int -> Int
f nm g a b = e nm $ g a b
-- Show evaluation of an Int
e :: String -> Int -> Int
e nm = r nm . trace ("Evaluating " ++ nm)
-- Show Int literal
i :: Int -> Int
i n = e (show n) n
multiply :: Int -> Int -> Int
multiply a b = e "multiply" $ (f "multiply's *" (*))
(e "multiply's a" a)
(e "multiply's b" b)
minus :: Int -> Int -> Int
minus a b = e "minus" $ (f "minus's -" (-))
(e "minus's a" a)
(e "minus's b" b)
minus2 :: Int -> Int -> Int
minus2 a b = e "minus2" $ (f "minus2's -" (-))
(e "minus2's b" b)
(e "minus2's a" a)
main :: IO ()
main = print $ minus2 (multiply (minus (i 3) (i 5)) (i 7)) (i 9)
Once you've solved the problem on paper, you can check your answer with the results of the above code run on GHC. It tells you what evaluation order your code uses when compiled with GHC.
You can alternatively run this through the Haskell compiler of your choice.
Related
I have a hard time to understand Currying in Haskell. I was not able to understand the already existing answers to this topic. I want to understand what the difference is between:
(Int -> Int) -> Int
and
Int -> (Int - > Int)
I think the answer has something to do with currying. I have already consulted some resources about the topic and I have got an idea.
Functions that have several parameters can be described as an array of elementary operations with one input and one output.
According to the online tutorial learnyouahaskell:
"Doing max 4 5 first creates a function that takes a parameter and returns either 4 or that parameter, depending on which is bigger. Then, 5 is applied to that function and that function produces our desired result."
So in this case the elementary basic operations are just comparing two values. And the first operation is
if "lowest value possible" > 4 then "lowest value possible" otherwise 4
The second operation is
if 4 > 5 then 4 otherwise 5
This would represent Int -> (Int -> Int) but what would (Int -> Int) -> Int be?
Int -> (Int -> Int)
is the same type as
Int -> Int -> Int
and is the type of a curried two-arguments function, both being integers. That is it is a function which takes an integer argument and returns a function, whose argument is another integer, and which finally returns an integer.
Possible calls are f 3 2 and f (7+4) (5*8).
Possible definitions are f a b = a+b and f a b = a*a+42*b.
Instead,
(Int -> Int) - > Int
is not a binary function, curried or not. It is a function with a single argument, and this argument is a function Int -> Int. The final result is an integer.
Possible calls are f (\x -> x+1), f id, and f g where g n = n*4+5.
Possible definitions are f h = h 45 and f h = h (h 6) + h 7 + 9.
The idea of partial function application is a hallmark of Haskell.
Exploiting partial application is natural. It is much how we think.
I fill my glass half with tea. Then I fill it completely with lemonaid.
m2 = max 4 --partial application (Int -> Int)
m2 5 -- full application (Int -> Int) -> Int
All functions in Haskell are curried. It is sometimes necessary to disable it with uncurry
m3 = uncurry max
m4 = m3 4 -- does not become (Int -> Int)
m4 3 -- is not (Int -> Int) -> Int -> Int
Does not work and the error has to do with partial application (Int -> Int) because the function now requires two parameters.
I am a Haskell beginner currently working through The Craft of Functional Programming 2nd Edition. One of the exercises in the book asks me to write an averageThree function, which I have did, and then a howManyAboveAverage function using the averageThree function.
I was a bit stuck on how to do this but I found a similar problem here. I used the solution given in my code however I am getting a parse error [FIXED].
Here is my new code:
averageThree :: Int -> Int -> Int -> Float
averageThree a b c = fromIntegral (a + b + c) / 3
howManyAverageThree :: Int -> Int -> Int -> Int
howManyAverageThree a b c = length $ filter (> avg) the_three
where avg = averageThree a b c
the_three = fromIntegral <$> [a,b,c]
EDIT: New Error
Error trace:
[1 of 1] Compiling Main ( average.hs, interpreted )
average.hs:7:36: Not in scope: `<$>'
Failed, modules loaded: none.
I use ghci version 7.6.3 for compilation. Since I'm following a textbook example I need to preserve the function signatures. How can I modify this code such that I no longer get the above error?
In Haskell, indentation does matter. You need to match the indentation in your where clause:
howManyAverageThree :: Int -> Int -> Int -> Int
howManyAverageThree a b c = length $ filter (> avg) the_three
where avg = averageThree a b c
the_three = fromIntegral[a b c]
EDIT:
Following your edit to the question, you need to look more closely at the definition of the_three:
the_three = fromIntegral[a b c]
fromIntegral has type :: (Integral a, Num b) => a -> b
If you want to the_three to be a list of numbers, you need to do a few things.
First, your list constructions needs ,'s inside it. Second, you need to map fromIntegral over each element of that list.
import Control.Applicative((<$>))
....
the_three = fromIntegral <$> [a,b,c]
This is the file I am trying to load:
import Data.List (foldl')
import Text.Printf (printf)
import Data.Char (ord)
--data IntParsedStr = Int | ParsingError
--data ParsingError = ParsingError String
asInt :: String -> Either String Integer
asInt "" = Left "Empty string"
asInt xs#(x:xt) | x == '-' = either Left (Right . ((-1) *)) (asInt' xt)
| otherwise = either Left Right (asInt' xs)
where asInt' :: String -> Either String Integer
asInt' "" = Left "No digits"
asInt' xs = foldl' step (Right 0) xs
where step :: Either String Integer -> Char -> Either String Integer
step (Left e) _ = Left e
step (Right ac) c = either Left (Right . (10 * ac + ) . fromIntegral) (charAsInt c)
charAsInt :: Char -> Either String Int
charAsInt c | between (ord '0') (ord c) (ord '9') = Right $ ord c - ord '0'
| otherwise = Left $ printf "'%c' is not a digit" c
checkPrecision str = either error ((str == ). show) (asInt str)
between :: Ord t => t -> t -> t -> Bool
between a b c = a <= b && b <= c
It loads without any problem in ghci but in hugs I get this error:
ERROR "folds.hs":17 - Syntax error in expression (unexpected `)')
Line 17 is the last in the definition of asInt function
Edit:
Hi!
I recently founded that this is in fact a known hugs issue as said in this question
where there is a link to the Hugs 98 Users Guide where says that
Legal expressions like (a+b+) and (a*b+) are rejected.
I believe this is a bug in Hugs, not a liberality of GHC. The Haskell 98 report (appropriate in the context of Hugs usage) says
Syntactic precedence rules apply to sections as follows. (op e) is legal if and only if (x op e) parses in the same way as (x op (e)); and similarly for (e op). For example, (*a+b) is syntactically invalid, but (+a*b) and (*(a+b)) are valid. Because (+) is left associative, (a+b+) is syntactically correct, but (+a+b) is not; the latter may legally be written as (+(a+b)).
I interpret that as allowing (10 * ac + ) since both (*) and (+) are left associative, and indeed (*) has higher precedence.
As pointed out in the comments, ((10 * ac) + ) is accepted by both, so is a workaround.
Interestingly, this isn't listed in the Hugs vs Haskell 98 page, so maybe Mark P. Jones reads this section of the report differently to me. Certainly I can forgive him for this; Gofer implemented constructor classes long before Haskell allowed them, and Hugs is still faster than GHCi at compilation, and still gives better error messages.
for a homework assignment, a subtask is to make the arithmetic functions (+), (-), (*) and div showable.
We're solved the rest of the assignment, but we're stuck here. Right now we're using the solution to this question here to distinguish between the operations:
showOp op = case op 3 3 of
6 -> "plus"
0 -> "minus"
9 -> "times"
1 -> "divide"
_ -> "undefined"
However, this strikes me as kind of ugly as things like showOp (\a b -> a * 3 - y) yield "plus".
Is there any way to better distinguish between the operators?
We are using winhugs atm with the appropriate switches -98 +o in order to be able to use the needed extensions.
Edit:
As requested, the actual assignment has to do with Arrays (specifically Array Int (Int -> Int -> Int)). It has to do with generating arrays of operators that fulfill certain conditions.
The assignment states:
Make the data type Array Int (Int->Int-Int) an Instance of Show. The arithmetic operations from the previous exercises should be represented as "plus", "minus", "times" and "div".
thx for any help in advance
Use induction :)
{-# LANGUAGE FlexibleInstances #-}
instance Eq (Int-> Int -> Int) where
f == g = induce f g where
base = 1
n = 2
induce f g = and [f 1 n' == g 1 n' | n' <- [base, n, n+1]]
instance Show (Int-> Int -> Int) where
show a = showOp a where
showOp op = case lookup op ops of
Just a -> a
otherwise -> "undefined"
ops = [((+),"plus")
,((-),"minus")
,((*),"times")
,(div,"divide")]
Output:
*Main> (\a b -> a * 3 - b) :: (Int->Int->Int)
undefined
Here is my first Haskell program. What parts would you write in a better way?
-- Multiplication table
-- Returns n*n multiplication table in base b
import Text.Printf
import Data.List
import Data.Char
-- Returns n*n multiplication table in base b
mulTable :: Int -> Int -> String
mulTable n b = foldl (++) (verticalHeader n b w) (map (line n b w) [0..n])
where
lo = 2* (logBase (fromIntegral b) (fromIntegral n))
w = 1+fromInteger (floor lo)
verticalHeader :: Int -> Int -> Int -> String
verticalHeader n b w = (foldl (++) tableHeader columnHeaders)
++ "\n"
++ minusSignLine
++ "\n"
where
tableHeader = replicate (w+2) ' '
columnHeaders = map (horizontalHeader b w) [0..n]
minusSignLine = concat ( replicate ((w+1)* (n+2)) "-" )
horizontalHeader :: Int -> Int -> Int -> String
horizontalHeader b w i = format i b w
line :: Int -> Int -> Int -> Int -> String
line n b w y = (foldl (++) ((format y b w) ++ "|" )
(map (element b w y) [0..n])) ++ "\n"
element :: Int -> Int -> Int -> Int -> String
element b w y x = format (y * x) b w
toBase :: Int -> Int -> [Int]
toBase b v = toBase' [] v where
toBase' a 0 = a
toBase' a v = toBase' (r:a) q where (q,r) = v `divMod` b
toAlphaDigits :: [Int] -> String
toAlphaDigits = map convert where
convert n | n < 10 = chr (n + ord '0')
| otherwise = chr (n + ord 'a' - 10)
format :: Int -> Int -> Int -> String
format v b w = concat spaces ++ digits ++ " "
where
digits = if v == 0
then "0"
else toAlphaDigits ( toBase b v )
l = length digits
spaceCount = if (l > w) then 0 else (w-l)
spaces = replicate spaceCount " "
Here are some suggestions:
To make the tabularity of the computation more obvious, I would pass the list [0..n] to the line function rather than passing n.
I would further split out the computation of the horizontal and vertical axes so that they are passed as arguments to mulTable rather than computed there.
Haskell is higher-order, and almost none of the computation has to do with multiplication. So I would change the name of mulTable to binopTable and pass the actual multiplication in as a parameter.
Finally, the formatting of individual numbers is repetitious. Why not pass \x -> format x b w as a parameter, eliminating the need for b and w?
The net effect of the changes I am suggesting is that you build a general higher-order function for creating tables for binary operators. Its type becomes something like
binopTable :: (i -> String) -> (i -> i -> i) -> [i] -> [i] -> String
and you wind up with a much more reusable function—for example, Boolean truth tables should be a piece of cake.
Higher-order and reusable is the Haskell Way.
You don't use anything from import Text.Printf.
Stylistically, you use more parentheses than necessary. Haskellers tend to find code more readable when it's cleaned of extraneous stuff like that. Instead of something like h x = f (g x), write h = f . g.
Nothing here really requires Int; (Integral a) => a ought to do.
foldl (++) x xs == concat $ x : xs: I trust the built-in concat to work better than your implementation.
Also, you should prefer foldr when the function is lazy in its second argument, as (++) is – because Haskell is lazy, this reduces stack space (and also works on infinite lists).
Also, unwords and unlines are shortcuts for intercalate " " and concat . map (++ "\n") respectively, i.e. "join with spaces" and "join with newlines (plus trailing newline)"; you can replace a couple things by those.
Unless you use big numbers, w = length $ takeWhile (<= n) $ iterate (* b) 1 is probably faster. Or, in the case of a lazy programmer, let w = length $ toBase b n.
concat ( (replicate ((w+1)* (n+2)) "-" ) == replicate ((w+1) * (n+2)) '-' – not sure how you missed this one, you got it right just a couple lines up.
You do the same thing with concat spaces, too. However, wouldn't it be easier to actually use the Text.Printf import and write printf "%*s " w digits?
Norman Ramsey gave excellent high-level (design) suggestions; Below are some low-level ones:
First, consult with HLint. HLint is a friendly program that gives you rudimentary advice on how to improve your Haskell code!
In your case HLint gives 7 suggestions. (mostly about redundant brackets)
Modify your code according to HLint's suggestions until it likes what you feed it.
More HLint-like stuff:
concat (replicate i "-"). Why not replicate i '-'?
Consult with Hoogle whenever there is reason to believe that a function you need is already available in Haskell's libraries. Haskell comes with tons of useful functions so Hoogle should come in handy quite often.
Need to concatenate strings? Search for [String] -> String, and voila you found concat. Now go replace all those folds.
The previous search also suggested unlines. Actually, this even better suits your needs. It's magic!
Optional: pause and thank in your heart to Neil M for making Hoogle and HLint, and thank others for making other good stuff like Haskell, bridges, tennis balls, and sanitation.
Now, for every function that takes several arguments of the same type, make it clear which means what, by giving them descriptive names. This is better than comments, but you can still use both.
So
-- Returns n*n multiplication table in base b
mulTable :: Int -> Int -> String
mulTable n b =
becomes
mulTable :: Int -> Int -> String
mulTable size base =
To soften the extra characters blow of the previous suggestion: When a function is only used once, and is not very useful by itself, put it inside its caller's scope in its where clause, where it could use the callers' variables, saving you the need to pass everything to it.
So
line :: Int -> Int -> Int -> Int -> String
line n b w y =
concat
$ format y b w
: "|"
: map (element b w y) [0 .. n]
element :: Int -> Int -> Int -> Int -> String
element b w y x = format (y * x) b w
becomes
line :: Int -> Int -> Int -> Int -> String
line n b w y =
concat
$ format y b w
: "|"
: map element [0 .. n]
where
element x = format (y * x) b w
You can even move line into mulTable's where clause; imho, you should.
If you find a where clause nested inside another where clause troubling, then I suggest to change your indentation habits. My recommendation is to use consistent indentation of always 2 or always 4 spaces. Then you can easily see, everywhere, where the where in the other where is at. ok
Below's what it looks like (with a few other changes in style):
import Data.List
import Data.Char
mulTable :: Int -> Int -> String
mulTable size base =
unlines $
[ vertHeaders
, minusSignsLine
] ++ map line [0 .. size]
where
vertHeaders =
concat
$ replicate (cellWidth + 2) ' '
: map horizontalHeader [0 .. size]
horizontalHeader i = format i base cellWidth
minusSignsLine = replicate ((cellWidth + 1) * (size + 2)) '-'
cellWidth = length $ toBase base (size * size)
line y =
concat
$ format y base cellWidth
: "|"
: map element [0 .. size]
where
element x = format (y * x) base cellWidth
toBase :: Integral i => i -> i -> [i]
toBase base
= reverse
. map (`mod` base)
. takeWhile (> 0)
. iterate (`div` base)
toAlphaDigit :: Int -> Char
toAlphaDigit n
| n < 10 = chr (n + ord '0')
| otherwise = chr (n + ord 'a' - 10)
format :: Int -> Int -> Int -> String
format v b w =
spaces ++ digits ++ " "
where
digits
| v == 0 = "0"
| otherwise = map toAlphaDigit (toBase b v)
spaces = replicate (w - length digits) ' '
0) add a main function :-) at least rudimentary
import System.Environment (getArgs)
import Control.Monad (liftM)
main :: IO ()
main = do
args <- liftM (map read) $ getArgs
case args of
(n:b:_) -> putStrLn $ mulTable n b
_ -> putStrLn "usage: nntable n base"
1) run ghc or runhaskell with -Wall; run through hlint.
While hlint doesn't suggest anything special here (only some redundant brackets), ghc will tell you that you don't actually need Text.Printf here...
2) try running it with base = 1 or base = 0 or base = -1
If you want multiline comments use:
{- A multiline
comment -}
Also, never use foldl, use foldl' instead, in cases where you are dealing with large lists which must be folded. It is more memory efficient.
A brief comments saying what each function does, its arguments and return value, is always good. I had to read the code pretty carefully to fully make sense of it.
Some would say if you do that, explicit type signatures may not be required. That's an aesthetic question, I don't have a strong opinion on it.
One minor caveat: if you do remove the type signatures, you'll automatically get the polymorphic Integral support ephemient mentioned, but you will still need one around toAlphaDigits because of the infamous "monomorphism restriction."