To the vultures who might say "Look it up in your textbook", or "Hoogle it", I did.
I came across the statement
recipe = (== "000001")
It looks like some sort of boolean to me but I'm not sure. I've tried testing it in different ways in GHCi but I couldn't figure out anything that works.
Can someone explain what it means, and this question will be a result the next time someone Googles Haskell (==" ")
It's a section. It's equivalent to recipe = \x -> x == "000001" (which in turn is the same as recipe x = x == "000001").
You can use GHCI to figure this one out.
In GHCI, put in let recipe = (== "000001"). Now we can see how it works. Try :t recipe to see what the type is. That returns recipe :: [Char] -> Bool, so it looks like this is a function that takes an list of Chars (a String) and returns a Bool.
If you test it, you'll find it returns False for any input except "000001".
Since == is an operator, you can partially apply it to one argument, and it will return a function that takes the other argument and returns the result. So here == "000001" returns a function that takes one argument to fill in the other side of the == and returns the result.
Edit: If the definition were recipe = ((==) "000001") this explanation would be right.
To understand this, you should look up partial application. The type of the == function is a -> a -> Bool, a function that takes two arguments of the same type and returns a Bool.
But it's also a function of type a -> (a -> Bool), that takes one argument of type a and returns a new function with the signature a -> Bool. That's what's happening here. We've supplied one argument to ==, so it returned a new function of type a -> Bool, or [Char] -> Bool in this particular case.
For binary operator # the expression (# x) would mean (\y -> y # x).
In your case it will be (\y -> y == "000001") ie. function that takes String and says if it is equal to "000001".
(== arg) or (arg ==) is an operator section (it works for other operators as well - not just ==). What it does is to partially apply the operator to the given operand. So (== "foo") is the same as \x -> x == "foo".
Related
Can someone explain to me step by step what this function means?
select :: (a->a->Bool) -> a -> a -> a
As the comments pointed out, this is not a function definition, but just a type signature. It says, for any type a which you are free to choose, this function expects:
A function that takes two values of type a and gives a Bool
Two values of type a
and it returns another value of type a. So for example, we could call:
select (<) 1 2
where a is Int, since (<) is a function that takes two Ints and returns a Bool. We could not call:
select isPrefixOf 1 2
because isPrefixOf :: (Eq a) => [a] -> [a] -> Bool -- i.e. it takes two lists (provided that the element type supports Equality), but numbers are not lists.
Signatures can tell us quite a lot, however, due to parametericity (aka free theorems). The details are quite techincal, but we can intuit that select must return one of its two arguments, because it has no other way to construct values of type a about which it knows nothing (and this can be proven).
But beyond that we can't really tell. Often you can tell almost certainly what a function does by its signature. But as I explored this signature, I found that there were actually quite a few functions it could be, from the most obvious:
select f x y = if f x y then x else y
to some rather exotic
select f x y = if f x x && f y y then x else y
And the name select doesn't help much -- it seems to tell us that it will return one of the two arguments, but the signature already told us that.
In working through a solution to the 8 Queens problem, a person used the following line of code:
sameDiag try qs = any (\(colDist,q) -> abs (try - q) == colDist) $ zip [1..] qs
try is an an item; qs is a list of the same items.
Can someone explain how colDist and q in the lambda function get bound to anything?
How did try and q used in the body of lambda function find their way into the same scope?
To the degree this is a Haskell idiom, what problem does this design approach help solve?
The function any is a higher-order function that takes 2 arguments:
the 1st argument is of type a -> Bool, i.e. a function from a to Bool
the 2nd argument is of type [a], i.e. a list of items of type a;
i.e. the 1st argument is a function that takes any element from the list passed as the 2nd argument, and returns a Bool based on that element. (well it can take any values of type a, not just the ones in that list, but it's quite obviously certain that any won't be invoking it with some arbitrary values of a but the ones from the list.)
You can then simplify thinking about the original snippet by doing a slight refactoring:
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f = (\(colDist, q) -> abs (try - q) == colDist)
which can be transformed into
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f (colDist, q) = abs (try - q) == colDist)
which in turn can be transformed into
sameDiag :: Int -> [Int] -> Bool
sameDiag try qs = any f xs
where
xs = zip [1..] qs
f pair = abs (try - q) == colDist) where (colDist, q) = pair
(Note that sameDiag could also have a more general type Integral a => a -> [a] -> Bool rather than the current monomorphic one)
— so how does the pair in f pair = ... get bound to a value? well, simple: it's just a function; whoever calls it must pass along a value for the pair argument. — when calling any with the first argument set to f, it's the invocation of the function any who's doing the calling of f, with individual elements of the list xs passed in as values of the argument pair.
and, since the contents of xs is a list of pairs, it's OK to pass an individual pair from this list to f as f expects it to be just that.
EDIT: a further explanation of any to address the asker's comment:
Is this a fair synthesis? This approach to designing a higher-order function allows the invoking code to change how f behaves AND invoke the higher-order function with a list that requires additional processing prior to being used to invoke f for every element in the list. Encapsulating the list processing (in this case with zip) seems the right thing to do, but is the intent of this additional processing really clear in the original one-liner above?
There's really no additional processing done by any prior to invoking f. There is just very minimalistic bookkeeping in addition to simply iterating through the passed in list xs: invoking f on the elements during the iteration, and immediately breaking the iteration and returning True the first time f returns True for any list element.
Most of the behavior of any is "implicit" though in that it's taken care of by Haskell's lazy evaluation, basic language semantics as well as existing functions, which any is composed of (well at least my version of it below, any' — I haven't taken a look at the built-in Prelude version of any yet but I'm sure it's not much different; just probably more heavily optimised).
In fact, any is simple it's almost trivial to re-implement it with a one liner on a GHCi prompt:
Prelude> let any' f xs = or (map f xs)
let's see now what GHC computes as its type:
Prelude> :t any'
any' :: (a -> Bool) -> [a] -> Bool
— same as the built-in any. So let's give it some trial runs:
Prelude> any' odd [1, 2, 3] -- any odd values in the list?
True
Prelude> any' even [1, 3] -- any even ones?
False
Prelude> let adult = (>=18)
Prelude> any' adult [17, 17, 16, 15, 17, 18]
— see how you can sometimes write code that almost looks like English with higher-order functions?
zip :: [a] -> [b] -> [(a,b)] takes two lists and joins them into pairs, dropping any remaining at the end.
any :: (a -> Bool) -> [a] -> Bool takes a function and a list of as and then returns True if any of the values returned true or not.
So colDist and q are the first and second elements of the pairs in the list made by zip [1..] qs, and they are bound when they are applied to the pair by any.
q is only bound within the body of the lambda function - this is the same as with lambda calculus. Since try was bound before in the function definition, it is still available in this inner scope. If you think of lambda calculus, the term \x.\y.x+y makes sense, despite the x and the y being bound at different times.
As for the design approach, this approach is much cleaner than trying to iterate or recurse through the list manually. It seems quite clear in its intentions to me (with respect to the larger codebase it comes from).
I've taken up learning Haskell again, after a short hiatus and I am currently trying to get a better understanding of how recursion and lambda expressions work in Haskell.
In this: YouTube video, there is a function example that puzzles me far more than it probably should, in terms of how it actually works:
firstThat :: (a -> Bool) -> a -> [a] -> a
firstThat f = foldr (\x acc -> if f x then x else acc)
For the sake of clarity and since it wasn't immediately obvious to me, I'll give an example of applying this function to some arguments:
firstThat (>10) 2000 [10,20,30,40] --returns 20, but would return 2000, if none of the values in the list were greater than 10
Please correct me, if my assumptions are wrong.
It seems firstThat takes three arguments:
a function that takes one arguments and returns a Boolean value. Since the > operator is actually an infix function, the first argument in the example above seems the result of a partial application to the > function – is this correct?
an unspecified value of the same type expected as the missing argument to the function provided as the first argument
a list of values of the aforementioned type
But the actual function firstThat seems to be defined differently from its type declaration, with just one argument. Since foldr normally takes three arguments I gathered there is some kind of partial application happening. The lambda expression provided as an argument to foldr seem to be missing its arguments too.
So, how exactly does this function work? I apologize if I am being too dense or fail to see the forest for the trees, but I just cannot wrap my head around it, which is frustrating.
Any helpful explanation or example(s) would be greatly appreciated.
Thanks!
But the actual function firstThat seems to be defined differently from its type declaration, with just one argument. Since foldr normally takes three arguments I gathered there is some kind of partial application happening.
You are right. However, there is a nicer way of putting it than talking about "missing arguments" -- one that doesn't lead you into asking where they have gone. Here are two ways in which the arguments are not missing.
Firstly, consider this function:
add :: Num a => a -> a -> a
add x y = x + y
As you may know, we can also define it like this:
add :: Num a => a -> a -> a
add = (+)
That works because Haskell functions are values like any other. We can simply define a value, add, as being equal to another value, (+), which just happens to be a function. There is no special syntax required to declare a function. The upshot is that writing arguments explicitly is (almost) never necessary; the main reason why we do so because it often makes code more readable (for instance, I could define firstThat without writing the f parameter explicitly, but I won't do so because the result is rather hideous).
Secondly, whenever you see a function type with three arguments...
firstThat :: (a -> Bool) -> a -> [a] -> a
... you can also read it like this...
firstThat :: (a -> Bool) -> (a -> [a] -> a)
... that is, a function of one argument that produces a function of two arguments. That works for all functions of more than one argument. The key takeaway is that, at heart, all Haskell functions take just one argument. That is why partial application works. So on seeing...
firstThat :: (a -> Bool) -> a -> [a] -> a
firstThat f = foldr (\x acc -> if f x then x else acc)
... you can accurately say that you have written explicitly all parameters that firstThat takes -- that is, only one :)
The lambda expression provided as an argument to foldr seem to be missing its arguments too.
Not really. foldr (when restricted to lists) is...
foldr :: (a -> b -> b) -> b -> [a] -> b
... and so the function passed to it takes two arguments (feel free to add air quotes around "two", given the discussion above). The lambda was written as...
\x acc -> if f x then x else acc
... with two explicit arguments, x and acc.
a function that takes one arguments and returns a Boolean value. Since the > operator is actually an infix function, the first argument in the example above seems the result of a partial application to the > function – is this correct?
yes: (>10) is short for \x -> x > 10, just as (10>) would be short for \x -> 10 > x.
an unspecified value of the same type expected as the missing argument to the function provided as the first argument
first of all, it's not a missing argument: by omitting an argument, you obtain a function value. however, the type of the 2nd argument does indeed match the argument of the function >10, just as it matches the type of the elements of the list [10,20,30,40] (which is better reasoning).
a list of values of the aforementioned type
yes.
But the actual function firstThat seems to be defined differently from its type declaration, with just one argument. Since foldr normally takes three arguments I gathered there is some kind of partial application happening. The lambda expression provided as an argument to foldr seem to be missing its arguments too.
that's because given e.g. foo x y z = x * y * z, these 2 lines are equivalent:
bar x = foo x
bar x y z = foo x y z
— that's because of a concept called currying. Currying is also the reason why function type signatures are not (a, b) -> c but instead a -> b -> c, which in turn is equivalent to a -> (b -> c) because of the right associativity of the -> type operator.
Therefore, these two lines are equivalent:
firstThat f = foldr (\x acc -> if f x then x else acc)
firstThat f x y = foldr (\x acc -> if f x then x else acc) x y
Note: that you can also use Data.List.find combined with Data.Maybe.fromMaybe:
λ> fromMaybe 2000 $ find (>10) [10, 20, 30]
20
λ> fromMaybe 2000 $ find (>10) [1, 2, 3]
2000
See also:
https://en.wikipedia.org/wiki/Currying.
https://www.fpcomplete.com/user/EFulmer/currying-and-partial-application
http://learnyouahaskell.com/higher-order-functions
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
I have to dessignate types of 2 functions(without using compiler :t) i just dont know how soudl i read these functions to make correct steps.
f x = map -1 x
f x = map (-1) x
Well i'm a bit confuse how it will be parsed
Function application, or "the empty space operator" has higher precedence than any operator symbol, so the first line parses as f x = map - (1 x), which will most likely1 be a type error.
The other example is parenthesized the way it looks, but note that (-1) desugars as negate 1. This is an exception from the normal rule, where operator sections like (+1) desugar as (\x -> x + 1), so this will also likely1 be a type error since map expects a function, not a number, as its first argument.
1 I say likely because it is technically possible to provide Num instances for functions which may allow this to type check.
For questions like this, the definitive answer is to check the Haskell Report. The relevant syntax hasn't changed from Haskell 98.
In particular, check the section on "Expressions". That should explain how expressions are parsed, operator precedence, and the like.
These functions do not have types, because they do not type check (you will get ridiculous type class constraints). To figure out why, you need to know that (-1) has type Num n => n, and you need to read up on how a - is interpreted with or without parens before it.
The following function is the "correct" version of your function:
f x = map (subtract 1) x
You should be able to figure out the type of this function, if I say that:
subtract 1 :: Num n => n -> n
map :: (a -> b) -> [a] -> [b]
well i did it by my self :P
(map) - (1 x)
(-)::Num a => a->a->->a
1::Num b=> b
x::e
map::(c->d)->[c]->[d]
map::a
a\(c->d)->[c]->[d]
(1 x)::a
1::e->a
f::(Num ((c->d)->[c]->[d]),Num (e->(c->d)->[c]->[d])) => e->(c->d)->[c]->[d]