Make "A || B && C" point-free in Haskell - haskell

I'm tackling a simple leap year exercise in Haskell, and I'd like to make my solution point-free. Starting from this:
isLeapYear :: Integer -> Bool
isLeapYear year = divisibleBy 400 year || divisibleBy 4 year && not (divisibleBy 100 year)
where
divisibleBy m y = (== 0) $ flip mod m y
I tried using liftA3, with a function doing (x || (y && z)) following this, but the tests do not finish and I don't know why.
So, then, I have 3 questions:
Do you have any pointers as to how could I achieve this?
In my first solution, what's preventing divisibleBy to be point-free? (Typechecker complains if I remove the arguments)
As I mentioned before, I tried something like liftA3 (\x y z -> x || (y && z)) (divisibleBy 400) (divisibleBy 4) (indivisibleBy 100), but the tests hang. Why does that happen? I'm not getting how liftA3 works.
Thanks a lot for your help.

In my first solution, what's preventing divisibleBy to be point-free? (Typechecker complains if I remove the arguments)
You might think that these are equivalent (I am writing flipmod as one function for simplicity's sake):
divisibleBy m y = (== 0) $ flipmod m y
divisibleBy' = (== 0) . flipmod
But in actuality, divisibleBy' is now an (invalid) function that takes an argument x and then compares flipmod x to zero:
((==0) . flipmod) 5
→ (==0) (flipmod 5)
→ flipmod 5 == 0
Comparing a function (flipmod 5) and a number is certainly no good.
You'd need to write something more sophisticated, namely:
divisibleBy = ((== 0) .) . flipmod
So that now, properly:
divisibleBy 5 6
→ (((== 0) .) (flipmod 5)) 6
→ ((== 0) . flipmod 5) 6
→ (== 0) (flipmod 5 6)
→ flipmod 5 6 == 0
This construction (f.).g can also be written as ((.).(.)) f g, and that operator is sometimes called dot. I don't think writing things like this is a very good idea, but it might answer your question.
The tests hang. Why does that happen?
I don't know. You'll probably need to provide an mcve here, because this works fine for me as a full program:
import Control.Applicative
isLeapYear :: Integer -> Bool
isLeapYear = liftA3 (\x y z -> x || (y && z))
(divisibleBy 400)
(divisibleBy 4)
(not . divisibleBy 100)
where
divisibleBy m y = (== 0) $ flip mod m y
main = print (filter isLeapYear [1850..1950])

Related

Just Int to Int

This code either returns the first factor of an Integer starting from 2 or returns nothing if it's a prime.
Example: firstFactorOf 24 returns "Just 2"
Example: firstFactorOf 11 returns "Nothing"
My question is, how would I return the value 2 rather than "Just 2" if there is a factor or return the value x if there is no factor.
firstFactorOf x
| m == Nothing = m
| otherwise = m
where m =(find p [2..x-1])
p y = mod x y == 0
//RETURNS:
ghci> firstFactorOf 24
Just 2
ghci> firstFactorOf 11
Nothing
Haskell is statically typed, meaning that you can define a function Maybe a -> a, but the question is what to do with the Nothing case.
Haskell has two functions that can be helpful here: fromMaybe and fromJust:
fromMaybe :: a -> Maybe a -> a
fromJust :: Maybe a -> a
fromJust simply assumes that you will always provide it a Just x, and return x, in the other case, it will throw an exception.
fromMaybe on the other hand expects two parameters, the first - an a is the "default case" the value that should be returned in case of Nothing. Next it is given a Maybe a and in case it is a Just x, x is returned. In the other case (Nothing) as said before the default is returned.
In your comment you say x should be returned in case no such factor exists. So I propose you define a new function:
firstFactorOfJust :: Integral a => a -> a
firstFactorOfJust x = fromMaybe x $ firstFactorOf x
So this function firstFactorOfJust calls your firstFactorOf function and if the result is Nothing, x will be returned. In the other case, the outcome of firstFactorOf will be returned (but only the Integral part, not the Just ... part).
EDIT (simplified)
Based on your own answer that had the intend to simplify things a bit, I had the idea that you can simplify it a bit more:
firstFactorOf x | Just z <- find ((0 ==) . mod x) [2..x-1] = z
| otherwise = x
and since we are all fan of optimization, you can already stop after sqrt(x) iterations (a well known optimization in prime checking):
isqrt :: Int -> Int
isqrt = floor . sqrt . fromIntegral
firstFactorOf x | Just z <- find ((0 ==) . mod x) [2..isqrt x] = z
| otherwise = x
Simplified question
For some reason there was some peculiarly complicated aspect in your question:
firstFactorOf x
| m == Nothing = m
| otherwise = m
where m =(find p [2..x-1])
p y = mod x y == 0
Why do you use guards to make a distinction between two cases that generate the exact same output? You can fold this into:
firstFactorOf x = m
where m = (find p [2..x-1])
p y = mod x y == 0
and even further:
firstFactorOf x = find p [2..x-1]
where p y = mod x y == 0
If you want it to return the first factor of x, or x, then this should work:
firstFactorOf x =
let
p y = mod x y == 0
m = (find p [2..x-1])
in
fromMaybe x m
import Data.List
import Data.Maybe
firstFactorOf x
| m == Nothing = x
| otherwise = fromJust m
where m =(find p [2..x-1])
p y = mod x y == 0
This was what I was after. Not sure why you guys made this so complicated.

Custom sine function in Functional Programming

Please help, I've been trying to get this code to work but I can't find the errors. Below is my code
sumToN f x 1 = f (x 1)
sumToN f x n = f x n + f x (n-1)
facOfN 0 = 1
facOfN n = n * facOfN (n-1) sgfr
sineApprox x n = ((-1) ^ n) * ((x ** (2*n+1))/facOfN(2*n+1)
sine x n = sumToN (sineApprox x n)
When I try to load the file I get the following error.
ERROR file:F:\sine.hs:8 - Syntax error in expression (unexpected `;', possibly due to bad layout)
Any assistance would be greatly appreciated.
As already said in the comments, you've forgotten to close a paren. It'll work like that:
sineApprox x n = ((-1) ^ n) * ((x ** (2*n+1))/facOfN(2*n+1))
Note that this problem would have been obvious with a better text editor. Being a beginner, I suggest you switch to iHaskell, which has a very simple interface and yet reasonably powerful editor features.
The problem would also have been obvious if you hadn't used so many unnecessary parens. The following can be omitted just like that, some can be replaced with $. While we're at style...
sumToN f x n -- checking ==1 is not safe in general
| n<=1 = f $ x 1
| otherwise = f x n + f x (n-1)
facOfN = product [1..n]
sineApprox x n = (-1)^n * x**(2*n+1) / facOfN (2*n+1)
sine x = sumToN . sineApprox x
On another note: in general, you should always use type signatures. This code actually has problems because all the counter variables are automaticall floating point (like everything else). They should really be Ints, which requires a conversions in the factorial†:
sumToN :: Num n => (Int -> n) -> Int -> n
sumToN f x n
| n<1 = 0
| otherwise = f x n + f x (n-1)
facOfN :: Num n => Int -> n
facOfN = product [1 .. fromIntegral n]
sineApprox :: Fractional n => n -> Int -> n
sineApprox x n = (-1)^n * x^(2*n+1) / facOfN (2*n+1)
sine
sine x = sumToN . sineApprox x
†BTW, explicitly using factorials is almost always a bad idea, as the numbers quickly get intractibly huge. Also, you're doing a lot of duplicate work. Better multiply as you add along!

FizzBuzz cleanup

I'm still learning Haskell, and I was wondering if there is a less verbose way to express the below statement using 1 line of code:
map (\x -> (x, (if mod x 3 == 0 then "fizz" else "") ++
if mod x 5 == 0 then "buzz" else "")) [1..100]
Produces:
[(1,""),(2,""),(3,"fizz"),(4,""),(5,"buzz"),(6,"fizz"),(7,""),(8,""),(9,"fizz"),(10,"buzz"),(11,""),(12,"fizz"),(13,""),(14,""),(15,"fizzbuzz"),(16,""),(17,""),(18,"fizz"),(19,""),(20,"buzz"),(21,"fizz"),(22,""),(23,""),(24,"fizz"),(25,"buzz"),(26,""),(27,"fizz"),(28,""),(29,""),(30,"fizzbuzz"), etc
It just feels like I'm fighting the syntax more than I should. I've seen other questions for this in Haskell, but I'm looking for the most optimal way to express this in a single statement (trying to understand how to work the syntax better).
We need no stinkin' mod...
zip [1..100] $ zipWith (++) (cycle ["","","fizz"]) (cycle ["","","","","buzz"])
or slightly shorter
import Data.Function(on)
zip [1..100] $ (zipWith (++) `on` cycle) ["","","fizz"] ["","","","","buzz"]
Or the brute force way:
zip [1..100] $ cycle ["","","fizz","","buzz","fizz","","","fizz","buzz","","fizz","","","fizzbuzz"]
If you insist on a one-liner:
[(x, concat $ ["fizz" | mod x 3 == 0] ++ ["buzz" | mod x 5 == 0]) | x <- [1..100]]
How's about...
fizzBuzz = [(x, fizz x ++ buzz x) | x <- [1..100]]
where fizz n | n `mod` 3 == 0 = "fizz"
| otherwise = ""
buzz n | n `mod` 5 == 0 = "buzz"
| otherwise = ""
Couldn't resist going in the other direction and making it more complicated. Look, no mod...
merge as#(a#(ia,sa):as') bs#(b#(ib,sb):bs') =
case compare ia ib of
LT -> a : merge as' bs
GT -> b : merge as bs'
EQ -> (ia, sa++sb) : merge as' bs'
merge as bs = as ++ bs
zz (n,s) = [(i, s) | i <- [n,2*n..]]
fizzBuzz = foldr merge [] $ map zz [(1,""), (3,"fizz"), (5,"buzz")]
Along the same lines as larsmans' answer:
fizzBuzz = [(x, f 3 "fizz" x ++ f 5 "buzz" x) | x <- [1..100]]
where f k s n | n `mod` k == 0 = s
| otherwise = ""
I think the reason why you feel like you are fighting the syntax is because you are mixing too many types.
Instead of trying to print:
[(1, ""), (2,""), (3,"Fizz")...]
Just think of printing strings:
["1","2","Fizz"...]
My attempt:
Prelude> let fizzBuzz x | x `mod` 15 == 0 = "FizzBuzz" | x `mod` 5 == 0 = "Buzz" | x `mod` 3 == 0 = "Fizz" | otherwise = show x
Prelude> [fizzBuzz x | x <-[1..100]]
["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"...]
In order to convert an Int to String you use the:
show x
Just for studying
zipWith (\a b -> b a) (map show [1..100]) $ cycle [id,id,const "fizz",id,const "buzz",const "fizz",id,id,const "fizz",const "buzz",id,const "fizz",id,id,const "fizzbuzz"]
produces
["1","2","fizz","4","buzz","fizz","7","8","fizz","buzz","11","fizz","13","14","fizzbuzz","16","17","fizz","19","buzz","fizz","22","23","fizz","buzz","26","fizz","28","29","fizzbuzz","31","32","fizz","34","buzz","fizz","37","38","fizz","buzz","41","fizz","43","44","fizzbuzz","46","47","fizz","49","buzz","fizz","52","53","fizz","buzz","56","fizz","58","59","fizzbuzz","61","62","fizz","64","buzz","fizz","67","68","fizz","buzz","71","fizz","73","74","fizzbuzz","76","77","fizz","79","buzz","fizz","82","83","fizz","buzz","86","fizz","88","89","fizzbuzz","91","92","fizz","94","buzz","fizz","97","98","fizz","buzz"]
Writer monad may look nice (if you don't like concat):
fizzBuzz = [(x, execWriter $ when (x `mod` 3 == 0) (tell "fizz") >> when (x `mod` 5 == 0) (tell "buzz")) | x <- [1..100]]
It's not particularly succinct though.

fizzbuzz in haskell?

I'm trying to write 'fizzbuzz' in haskell using list comprehensions.
Why doesn't the following work, and how should it be?
[ if x `mod` 5 == 0 then "BUZZFIZZ"
if x `mod` 3 == 0 then "BUZZ"
if x `mod` 4 == 0 then "FIZZ" | x <- [1..20],
x `mod` 3 == 0,
x `mod` 4 == 0,
x `mod` 5 == 0 ]
This isn't valid Haskell. The else branch is not optional in if ... then ... else. Rather than using if, this seems like a good opportunity to use a case statement.
case (x `rem` 3, x `rem` 5) of
(0,0) -> "fizzbuzz"
(0,_) -> "fizz"
(_,0) -> "buzz"
_ -> show x
This snippet will work for a traditional "fizzbuzz"; your code seems to be slightly different.
First of all, you're missing the else parts of your if expressions. In Haskell, if is an expression, not a statement, so the else part is mandatory.
Secondly, the list comprehension only produces any values if all the guard expressions evaluate to True. There is no number between 1 and 20 that is 0 modulo 3, 4, and 5, so you'll get no results. You'll want to use || (logical OR) to combine them instead.
Third, most definitions of FizzBuzz want you to return the number itself if it does not meet any of the other conditions. In that case, you'll want to use show to convert the number to a String.
Here's another version that can be extended to an arbitrary number of substitutions:
fizzbuzz' :: [(Integer, String)] -> Integer -> String
fizzbuzz' ss n = foldl (\str (num, subst) -> if n `mod` num == 0 then str ++ subst else str ++ "") "" ss
fizzbuzz :: [(Integer, String)] -> Integer -> String
fizzbuzz ss n = if null str then show n else str
where str = fizzbuzz' ss n
You could inline fizzbuzz' in the where clause of fizzbuzz, but I found a separate function easier for testing.
You can run it like this:
λ> mapM_ putStrLn $ map (fizzbuzz [(3, "fizz"), (5, "buzz")]) [9..15]
fizz
buzz
11
fizz
13
14
fizzbuzz
Or with extra substitutions:
λ> mapM_ putStrLn $ map (fizzbuzz [(3, "fizz"), (5, "buzz"), (7, "dazz")]) [19..24]
19
buzz
fizzdazz
22
23
fizz
In general, it helps if you give the error as well, not just the code.
But in this case, the problem is that every if needs an else clause. Keep in mind that an if statement is just an expression, so both branches must return a value of an appropriate type.
You've got several bugs in the code, by the way, but that's the only compiler error.
Here is a response to the traditional FizzBuzz problem using list comprehension + guards.
fizzbuzz = [fb x| x <- [1..100]]
where fb y
| y `mod` 15 == 0 = "FizzBuzz"
| y `mod` 3 == 0 = "Fizz"
| y `mod` 5 == 0 = "Buzz"
| otherwise = show y
Or alternatively don't be afraid to move where clause into separate succinct function for evaluating x then call that function from your list comprehension. Its better to build on small concise functions than trying to solve it in one more complex function. e.g.
fizzval x
| x `mod` 15 == 0 = "FizzBuzz"
| x `mod` 3 == 0 = "Fizz"
| x `mod` 5 == 0 = "Buzz"
| otherwise = show x
fizzbuzz = [fizzval x| x <- [1..100]]
With the help of some judicious currying, Calvin Bottoms did it in 77 characters.
http://freshbrewedcode.com/calvinbottoms/2012/02/25/fizzbuzz-in-haskell/
[max(show x)(concat[n|(f,n)<-[(3,"Fizz"),(5,"Buzz")],mod x f==0])|x<-[1..25]]
The Monad Reader contains a solution as well as many valuable insights and some more fun exercises. The solution is copied here for those who just want to see it.
fizzbuzz :: Int -> String
fizzbuzz n = (test 3 "fizz" . test 5 "buzz") id (show n)
where test d s x | n `mod` d == 0 = const (s ++ x "")
| otherwise = x
There is no x that fullfills the condition to be divisible by 3, 4 and 5 in the range 1..20.
Therefore, you would get an empty list if the example were syntactically correct, which it is not.

Comparing 3 output lists in haskell

I am doing another Project Euler problem and I need to find when the result of these 3 lists is equal (we are given 40755 as the first time they are equal, I need to find the next:
hexag n = [ n*(2*n-1) | n <- [40755..]]
penta n = [ n*(3*n-1)/2 | n <- [40755..]]
trian n = [ n*(n+1)/2 | n <- [40755..]]
I tried adding in the other lists as predicates of the first list, but that didn't work:
hexag n = [ n*(2*n-1) | n <- [40755..], penta n == n, trian n == n]
I am stuck as to where to to go from here.
I tried graphing the function and even calculus but to no avail, so I must resort to a Haskell solution.
Your functions are weird. They get n and then ignore it?
You also have a confusion between function's inputs and outputs. The 40755th hexagonal number is 3321899295, not 40755.
If you really want a spoiler to the problem (but doesn't that miss the point?):
binarySearch :: Integral a => (a -> Bool) -> a -> a -> a
binarySearch func low high
| low == high = low
| func mid = search low mid
| otherwise = search (mid + 1) high
where
search = binarySearch func
mid = (low+high) `div` 2
infiniteBinarySearch :: Integral a => (a -> Bool) -> a
infiniteBinarySearch func =
binarySearch func ((lim+1) `div` 2) lim
where
lim = head . filter func . lims $ 0
lims x = x:lims (2*x+1)
inIncreasingSerie :: (Ord a, Integral i) => (i -> a) -> a -> Bool
inIncreasingSerie func val =
val == func (infiniteBinarySearch ((>= val) . func))
figureNum :: Integer -> Integer -> Integer
figureNum shape index = (index*((shape-2)*index+4-shape)) `div` 2
main :: IO ()
main =
print . head . filter r $ map (figureNum 6) [144..]
where
r x = inIncreasingSerie (figureNum 5) x && inIncreasingSerie (figureNum 3) x
Here's a simple, direct answer to exactly the question you gave:
*Main> take 1 $ filter (\(x,y,z) -> (x == y) && (y == z)) $ zip3 [1,2,3] [4,2,6] [8,2,9]
[(2,2,2)]
Of course, yairchu's answer might be more useful in actually solving the Euler question :)
There's at least a couple ways you can do this.
You could look at the first item, and compare the rest of the items to it:
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [4,5,6] ]
False
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [1,2,3] ]
True
Or you could make an explicitly recursive function similar to the previous:
-- test.hs
f [] = True
f (x:xs) = f' x xs where
f' orig (y:ys) = if orig == y then f' orig ys else False
f' _ [] = True
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> f [ [1,2,3], [1,2,3], [1,2,3] ]
True
*Main> f [ [1,2,3], [1,2,3], [4,5,6] ]
False
You could also do a takeWhile and compare the length of the returned list, but that would be neither efficient nor typically Haskell.
Oops, just saw that didn't answer your question at all. Marking this as CW in case anyone stumbles upon your question via Google.
The easiest way is to respecify your problem slightly
Rather than deal with three lists (note the removal of the superfluous n argument):
hexag = [ n*(2*n-1) | n <- [40755..]]
penta = [ n*(3*n-1)/2 | n <- [40755..]]
trian = [ n*(n+1)/2 | n <- [40755..]]
You could, for instance generate one list:
matches :: [Int]
matches = matches' 40755
matches' :: Int -> [Int]
matches' n
| hex == pen && pen == tri = n : matches (n + 1)
| otherwise = matches (n + 1) where
hex = n*(2*n-1)
pen = n*(3*n-1)/2
tri = n*(n+1)/2
Now, you could then try to optimize this for performance by noticing recurrences. For instance when computing the next match at (n + 1):
(n+1)*(n+2)/2 - n*(n+1)/2 = n + 1
so you could just add (n + 1) to the previous tri to obtain the new tri value.
Similar algebraic simplifications can be applied to the other two functions, and you can carry all of them in accumulating parameters to the function matches'.
That said, there are more efficient ways to tackle this problem.

Resources