GHCI vs compiled function difference - haskell

The goal is to input a float and return a string containing only the absolute value of the digits before the dot.
Basically putting in -14.4 should return "14"
When I type in the sequence of instructions via GHCI I run into no problem.
Yet when I use it in a compiled function like this:
testFront :: Float -> String
testFront x = tillDot $ show $ abs $ x
tillDot :: String -> String
tillDot x = case x of
[] -> ""
x -> takeWhile (/= '.') x
then suddenly I run into the error shown in the the screenshot.
I figured out that I had to put the negative number using ().
The question is: Can I somehow do this within the file? Something that automatically puts my input into ()? Or do I have to write a seperate function that does that?

The question is: Can I somehow do this within the file? Something that automatically puts my input into ()? Or do I have to write a seperate function that does that?
The reason you need to wrap these into parenthesis is because there is a difference between:
f - 14
and:
f (-14)
Indeed, for the former it will subtract 14 from the value of a variable named f. If f is for example 25, it will return 11.
For the latter it will call a function f with -14 as argument.
Except for a minus, no operator has an unary form. The parenthesis are thus necessary to disambiguate between the unary and binary form.

Related

Why is (.) called infix as just . rather than `(.)`

I learned that functions can be invoked in two ways; prefix and infix. For example, say I've created this function:
example :: [Char] -> [Char] -> [Char]
example x y = x ++ " " ++ y
I can call it prefix like so:
example "Hello" "World"
or infix like so:
"Hello" `example` "World"
Both of which will result in the list of chars representing a string "Hello World".
However, I am now learning about function composition, and have come across the function defined like so:
(.) :: (b -> c) -> (a -> b) -> a -> c
So, say I was wanting to compose negate with multiplication by three. I would write the prefix invocation like:
negateComposedWithMultByThree = (.) negate (*3)
And the infix invocation like:
negateComposedWithMultByThree = negate `(.)` (*3)
But, whilst the prefix invocation compiles, the infix invocation does not and instead gives me the error message:
error: parse error on input `('
It seems, in order to call compose infix, I need to omit the brackets and call it like so:
negateComposedWithMultByThree = negate . (*3)
Can anyone shed any light on this? Why does "Hello" `example` "World" whilst negate `(.)` (*3) does not?
In addition, if I try to make my own function with a signature like this:
(,) :: Int -> Int
(,) x = 1
It does not compile, with the error:
"Invalid type signature (,) : ... Should be of form :: "
There's nothing deep here. There's just two kinds of identifiers that have different rules about how they're parsed: by-default-infix, and by-default-prefix. You can tell which is which, because by-default-infix identifiers contain only punctuation, while by-default-prefix identifiers contain only numbers, letters, apostrophes, and underscores.
Recognizing that the default isn't always the right choice, the language provides conversions away from the default behavior. So there are two separate syntax rules, one that converts a by-default-infix identifier to prefix (add parentheses), and one that converts a by-default-prefix identifier to infix (add backticks). You can not nest these conversions: a by-default-infix identifier converted to prefix form is not a by-default-prefix identifier.
That's it. Nothing fundamentally interesting -- all of them become just function applications once parsed -- it's just syntax sugar.

Operator as an argument in Haskell

I'm quite new to Haskell, may be it's a stupid question.
What I want is to give to my function as an argument any operator.
For example:
myFunc :: a -> Int -> Int -> Boolean
myFunc operator a b = a operator b
*Project> myFunc (>) 5 2
True
*Project> myFunc (<=) 5 2
False
Help me in advice how to do that please!
You can do that with haskell function arguments.
In your function above, you want myFunc to take a function that takes two Ints and returns a Bool (not a Boolean, you must have typed that wrong). The declaration for that function would be (Int -> Int -> Bool). Therefore, you can write:
myFunc :: (Int -> Int -> Bool) -> Int -> Int -> Bool
myFunc op a b = a `op` b
This defines a higher-order function that takes a function with two Int parameters that returns a Bool (and two Ints). You can now use it like any other function parameter!
Note that this is exactly the same as doing:
myFunc (#) a b = a # b
Or:
myFunc (%) a b = a % b
Because using infix operaters like * or /, or any operator composed only of special characters, without backticks is just shorthand for using them with (typing `/` every time you want to divide something would get annoying!).
Under the hood, functions "exist" without names. Any function you define (or that is already defined in libraries), such as myFunc just is a function value, and the name just gives us a way to refer to it in other code that wants to use it. This is exactly the same as if you write x = 3: the value 3 "exists" independently of the name x, that name just gives us a way to refer to it.
Why is this relevant to your question about passing operators?
Well, as far as Haskell is concerned, operators like > and <= are also just nameless functions that happen to be bound to the names > and <=. The special treatment of them as operators (that you can write them infix between the arguments you're calling them on) is only about the names, and changes if you refer to them with different names.
There are two types of names in Haskell. Alphanumeric names (consisting only of letters, numbers, and underscores), and symbolic names (consisting only of symbol characters). If you have an expression {1} {2} {3}, then if {2} is a symbolic name (and {1} and {3} aren't symbolic names; otherwise you have a syntax error), then the expression is interpreted as meaning "call {2} on the arguments {1} and {3}". But if none of them are symbolic names, then it's instead interpreted as "call {1} on the arguments {2} and {3}".1
But all of this happens only with reference to the name, not to the functions actually referred to by those names. So if you write your myFunc like so:
myFunc operator a b = operator a b
Then it doesn't actually matter whether myFunc was called like myFunc (+) 1 2 or like myFunc plus 1 2; inside the definition of myFunc the "operator" is referred to by the name operator, which is an alphanumeric name. So you put it first when you want to call it, with its arguments following.
Alternatively you could use a symbolic name inside myFunc, like so:
myFunc ($&^*) a b = a $&^* b
Again, this also works even when myFunc was called with a non-operator function like myFunc plus 1 2.
And of course, there are ways to convert either kind of name to work like the other; you can put an alphanumeric name in backticks to use it infix like an operator:
myFunc operator a b = a `operator` b
And you can put a symbolic name in parentheses to simply use it as reference to the function it's bound to (and this is in fact the only way to use an operator without providing arguments for it):
myFunc ($^&*) a b = ($&^*) a b
So basically, the only special thing you needed to know to pass an operator to your function is what you already knew: put the operator in parentheses when you call the function. Inside the definition of the function, you can write it exactly the same as any other function; the style of name you choose in that function definition will determine whether you call it like an operator or like an ordinary function. You don't need to know (and in fact cannot find out) whether it was an operator "outside" the function.
1 Of course, when you have more complex expressions involving more than 3 things and multiple operators, then the rules of precedence and associativity come into play to determine exactly what's going on.

Haskell - passing a function as a argument compilation error

I have a very simple function called 'fold' that takes a function f and executes it. Given a function 'add' and two numbers it calls add with those two numbers and displays the results. However I cannot compile it due to a compilation error below. What is the error specifically stating and what can I do to solve it?
module Main where
add x y = x + y
--fold :: ((a,b)->c) -> a->b->c
fold f n x = f n x
main :: IO ()
main = do
fold add 2 3
The problem is that you've declared main (correctly) as having type IO (), but fold doesn't return that. The error message is a little more complicated because in theory, add (and thus fold) could return a value of type IO (), since add can return any type with a Num instance. IO (), however, is not an instance of Num. The solution is to return an IO action created from the return value of fold. One way to do that is to use the print function (which takes any value with a Show instance and converts it to a String before outputing it).
main = print $ fold add 2 3

Why am I receiving this syntax error - possibly due to bad layout?

I've just started trying to learn haskell and functional programming. I'm trying to write this function that will convert a binary string into its decimal equivalent. Please could someone point out why I am constantly getting the error:
"BinToDecimal.hs":19 - Syntax error in expression (unexpected `}', possibly due to bad layout)
module BinToDecimal where
total :: [Integer]
total = []
binToDecimal :: String -> Integer
binToDecimal a = if (null a) then (sum total)
else if (head a == "0") then binToDecimal (tail a)
else if (head a == "1") then total ++ (2^((length a)-1))
binToDecimal (tail a)
So, total may not be doing what you think it is. total isn't a mutable variable that you're changing, it will always be the empty list []. I think your function should include another parameter for the list you're building up. I would implement this by having binToDecimal call a helper function with the starting case of an empty list, like so:
binToDecimal :: String -> Integer
binToDecimal s = binToDecimal' s []
binToDecimal' :: String -> [Integer] -> Integer
-- implement binToDecimal' here
In addition to what #Sibi has said, I would highly recommend using pattern matching rather than nested if-else. For example, I'd implement the base case of binToDecimal' like so:
binToDecimal' :: String -> [Integer] -> Integer
binToDecimal' "" total = sum total -- when the first argument is the empty string, just sum total. Equivalent to `if (null a) then (sum total)`
-- Include other pattern matching statements here to handle your other if/else cases
If you think it'd be helpful, I can provide the full implementation of this function instead of giving tips.
Ok, let me give you hints to get you started:
You cannot do head a == "0" because "0" is String. Since the type of a is [Char], the type of head a is Char and you have to compare it with an Char. You can solve it using head a == '0'. Note that "0" and '0' are different.
Similarly, rectify your type error in head a == "1"
This won't typecheck: total ++ (2^((length a)-1)) because the type of total is [Integer] and the type of (2^((length a)-1)) is Integer. For the function ++ to typecheck both arguments passed to it should be list of the same type.
You are possible missing an else block at last. (before the code binToDecimal (tail a))
That being said, instead of using nested if else expression, try to use guards as they will increase the readability greatly.
There are many things we can improve here (but no worries, this is perfectly normal in the beginning, there is so much to learn when we start Haskell!!!).
First of all, a string is definitely not an appropriate way to represent a binary, because nothing prevents us to write "éaldkgjasdg" in place of a proper binary. So, the first thing is to define our binary type:
data Binary = Zero | One deriving (Show)
We just say that it can be Zero or One. The deriving (Show) will allow us to have the result displayed when run in GHCI.
In Haskell to solve problem we tend to start with a more general case to dive then in our particular case. The thing we need here is a function with an additional argument which holds the total. Note the use of pattern matching instead of ifs which makes the function easier to read.
binToDecimalAcc :: [Binary] -> Integer -> Integer
binToDecimalAcc [] acc = acc
binToDecimalAcc (Zero:xs) acc = binToDecimalAcc xs acc
binToDecimalAcc (One:xs) acc = binToDecimalAcc xs $ acc + 2^(length xs)
Finally, since we want only to have to pass a single parameter we define or specific function where the acc value is 0:
binToDecimal :: [Binary] -> Integer
binToDecimal binaries = binToDecimalAcc binaries 0
We can run a test in GHCI:
test1 = binToDecimal [One, Zero, One, Zero, One, Zero]
> 42
OK, all fine, but what if you really need to convert a string to a decimal? Then, we need a function able to convert this string to a binary. The problem as seen above is that not all strings are proper binaries. To handle this, we will need to report some sort of error. The solution I will use here is very common in Haskell: it is to use "Maybe". If the string is correct, it will return "Just result" else it will return "Nothing". Let's see that in practice!
The first function we will write is to convert a char to a binary. As discussed above, Nothing represents an error.
charToBinary :: Char -> Maybe Binary
charToBinary '0' = Just Zero
charToBinary '1' = Just One
charToBinary _ = Nothing
Then, we can write a function for a whole string (which is a list of Char). So [Char] is equivalent to String. I used it here to make clearer that we are dealing with a list.
stringToBinary :: [Char] -> Maybe [Binary]
stringToBinary [] = Just []
stringToBinary chars = mapM charToBinary chars
The function mapM is a kind of variation of map which acts on monads (Maybe is actually a monad). To learn about monads I recommend reading Learn You a Haskell for Great Good!
http://learnyouahaskell.com/a-fistful-of-monads
We can notice once more that if there are any errors, Nothing will be returned.
A dedicated function to convert strings holding binaries can now be written.
binStringToDecimal :: [Char] -> Maybe Integer
binStringToDecimal = fmap binToDecimal . stringToBinary
The use of the "." function allow us to define this function as an equality with another function, so we do not need to mention the parameter (point free notation).
The fmap function allow us to run binToDecimal (which expect a [Binary] as argument) on the return of stringToBinary (which is of type "Maybe [Binary]"). Once again, Learn you a Haskell... is a very good reference to learn more about fmap:
http://learnyouahaskell.com/functors-applicative-functors-and-monoids
Now, we can run a second test:
test2 = binStringToDecimal "101010"
> Just 42
And finally, we can test our error handling system with a mistake in the string:
test3 = binStringToDecimal "102010"
> Nothing

function parameters in haskell

I can use parenthesis to make cons operator have more priority than function application in this patter match equation:
tail (_:xs) = xs
However it will be "parse error in pattern" if I try to write this:
f (g x) = 7
I see that g x produces a value and we should directly pass that value. Or in this way f g x = g x + 7 we make a call to g with an argument x in the body of f definition.
But what is the reason for not allowing to pass a function call in the pattern?
A pattern match is about destructuring things. Think along the lines of "I have build this data using constructor A". With pattern matching we could see what values we supplied A.
This means that means that constructors have to be invertible, we need to be able to figure out a constructors inputs given the results. Now if you wanted to do the same thing with a function call you'd be in trouble since you can't just invert a function, imagine f = const 0.
What it sounds like you want instead is a view pattern. This is where you are passed data, feed it into a function, and then pattern match on the result.
{-# LANGUAGE ViewPatterns #-}
foo (bar -> Just a) = a
This should be read as "Feed the argument to bar, then pattern match on the resulting Maybe".
We don't pass anything in a pattern. We describe how data that is passed must look like for the corresponding equation to take effect.
Now, it turns out that every value is of the form g x for some combination of g and x, so the pattern g x can be abbreviated to just x.

Resources