Related
I'm learning Haskell.
One of my standard techniques when learning a new language is to implement a Hello World genetic algorithm that attempts to generate a string via genetic algorithm techniques that matches some input string.
Due to my inexperience with Haskell (the closest thing I have to compare is Kotlin) I searched for an example code so I could match my existing understanding of basic genetic algorithm to the code and intuit some understanding of Haskell based on my already underway reading/research on the language.
I came across this tutorial: https://www.arcadianvisions.com/blog/2011/haskell-genetic-algorithm-hello-world.html
I transcribed it in atom after setting my environment up, each part I didn't understand I did a quick google, if I didn't understand the syntax/semantics after 15 minutes I would carry on transcribing with the intent to catch up later on those particular parts.
So, I understood most of the code, such as the order of function application, monads (think I'm nearly there with monads anyway), data types, function types, currying, type substitution etc. However, there were several bits of syntax/semantics that I haven't seen in my reading/researching and not sure what they do, but they appear a lot in the code example I linked to above. I'm hoping someone can explain them to me:
(++)
(:)
<$>
<*>
(,)
(x !!)
p#(info#())
I am assuming the () and <> are some special syntax and the stuff inside them is semantic? When I hover over them in atom (I'm using atom-haskell-ghc) I can see the type Functor f => Applicative (f :: * -> *) where <*> :: f (a -> b) -> f a -> f b which kind of looks like a monad, but I don't really understand the weird syntax/semantics on the consuming end. Should I think of these as just another function (with a weird infix alias?).
Here is a specific line exhibiting several of the examples from above:
mate :: RandomGen g => Gene -> Gene -> Rand g Gene
mate gene1 gene2 = (++) <$> flip take gene1 <*> flip drop gene2 <$> pivot
where pivot = getRandomR (0, length gene1 - 1)
A note on operators
In Haskell you can define a function that has as identifier a sequence of symbols wrapped between brackets, like for example (++) or (:) that is an operator that can be used both as a function, like (++) x y, and as an infix operator, like x ++ y. Behind the curtains, the Haskell compiler will convert the infix operator to a function call, so x ++ y is completely equivalent with (++) x y (except for the fact that operators have different precedence rules).
(++)
This is the append function: (++) :: [a] -> [a] -> [a] it takes two lists as input, and constructs a list of the same type of elements that contains the elements of the first list followed by the elements of the second list. For example:
(++) [1, 4, 2, 5] [1, 3, 0, 2] == [1, 4, 2, 5, 1, 3, 0, 2]
(:)
This is a constructor of the list type [a]. It has type (:) :: a -> [a] -> [a]. It takes as input an element and a list of elements (all of the same type), it construct a list that starts with the first element, followed by the elements of the second parameter. For example:
(:) 1 [4, 2, 5] = [1, 4, 2, 5]
(<$>)
You wrote in your question <$>, but as you perhaps figured out, that means that somewhere a function (<$>) :: Functor f => (a -> b) -> f a -> f b is defined.
A Functor is a typeclass. Several types in Haskell are functors. The easiest ones are a list [], and a Maybe. The (<$>) takes as input a function f :: a -> b, and a functor instance, for example a list [a]. It will then convert it to a functor instance [b]. How this is done, depends on how the Functor instance is implemented (the (<$>) for a Maybe has different semantics than one for []).
Although the analogy is not complete, you can see a Functor sometimes as a collection of elements (a Maybe basically is a collection of zero Nothing, or one Just x elements). It will then map the elements the collection contains by channeling these through the function, for example:
(+1) <$> [1, 4, 2, 5] == [2, 5, 3, 6]
(+1) <$> Nothing == Nothing
(+1) <$> (Just 2) == Just 3
(<*>)
This function (<*>) :: Applicative f => f (a -> b) -> f a -> f b is again somewhat hard to understand. It makes use of an Applicative type class.
An type that is an instance of Applicative has to implement two functions: pure :: Applicative a => a -> f a and (<*>) :: Applicative f => f (a -> b) -> f a -> f b (or the programmer can decide to instead implement liftA2, but let us ignore that here).
Again you can see Applicative (at least for popular instances) as a collection (like [] or Maybe). Here we thus take as input such collection of functions (all with type a -> b), and a collection of as. We then "multiply" these, in the sense that for instance for a list:
[f1, f2, ..., fm] <*> [x1, x2, ..., xn]
== [f1 x1, f1 x2, ..., f1 xn,
f2 x1, f2 x2, ..., f2 xn,
...,
fm x1, fm x2, ..., fm xn]
So that means for instance for Maybe that if the left operand is Nothing, or the right operand is Nothing, or both are Nothing, then this results in a Nothing, if both are Justs (so Just f <*> Just x), then we obtain a Just (f x):
Just f <*> Just x == Just (f x)
Just f <*> Nothing == Nothing
Nothing <*> Just x == Nothing
Nothing <*> Nothing == Nothing
(,)
This is the constructor of a 2-tuple: (,) :: a -> b -> (a,b) thus takes as input an a and a b, and it constructs an 2-tuple where the first item is the first parameter, and the second item is the second parameter. For example:
(,) 4 'a' == (4, 'a')
(x !!)
This is a section of an infix operator. You can use an infix operator, and for instance specify the left or the right part. In that case you thus construct a partially applied function. For example:
([1, 4, 2, 5] !!) == (!!) [1, 4, 2, 5]
(!! 2) == flip (!!) 2
So for the latter it thus means that we constructed a function that takes as input a parameter that will be filled in as left operand. So:
(!! 2) [1, 4, 2, 5] == (!!) [1, 4, 2, 5]
The (!!) :: [a] -> Int -> a function takes as input a list and an Int and it returns the element at that index (zero-based indices).
p#(info#())
In contrast to the above, the # is not a function or operator (well these are actually the same), but a keyword.
It is used in pattern matching to obtain a reference to both an pattern and for instance match subpatterns (or obtain references to subpatterns).
For instance, say we want to pattern match a 2-tuple, and we want to have a reference to the entire tuple, and the first element, we can use:
somefunction total#(left, _) = ...
So if we then call somefunction (4, 'a'), then this means that total will hold (4, 'a'), and left will hold 4.
These are mostly all regular functions.
The <> are not special syntax, just part of the function name.
The () are regular parenthesis which group things and define precedence like in most other languages, the important note is that when you want to refer to an operator function (like ++) it must be in parenthesis.
++ is the list concatenation function [1,2] ++ [3,4] = [1,2,3,4], or without using infix notation (++) [1,2] [3,4] = [1,2,3,4]
: is the 'cons' function, it prepends an element to a list 1 : [2, 3, 4] = [1,2,3,4] or (:) 1 [2, 3, 4] = [1,2,3,4] without infix notation.
<$> is an infix operator alias of fmap
<*> is the applicative application function
, is the tuple constructor (,) 1 2 = (1, 2)
!! is the list index function [1,2,3] !! 1 = 2. Note that since these are singly linked lists, indexing is an O(n) operation.
# is used to define an "as pattern". When pattern matching it allows you to give a name to a parameter, while also destructuring it with pattern matching. For example the pattern f (xs#[x1, x2]) matches a two element list, where you can use x1 and x2 to refer to the individual elements and xs to refer to the list as a whole
I am posting below some code in Haskell. Please treat the code as an example, which I am going to use, to explain what I would like to know.
try :: [[Char]] -> [[Char]] -> [[Char]] -> [[Char]]
try (a:as) (b:bs) (c:cs) | ((checkIfCorrect a b c) == True) = a:b:[c]
| otherwise = try as bs cs
checkIfCorrect :: [Char] -> [Char] -> [Char] -> Bool
checkIfCorrect a b c = True
Eventually, checkIfCorrect returns True for only one combination of arguments. checkIfCorrect is really long function, so I decided to post substitute here. In the example above, function checkIfCorrect is applicated (by function try) to: first [Char] on the first list, first [Char] on the second list and first [Char] one the third list. If first guarded equation is not fulfilled, function checkIfCorrect is applied to: second [Char] on the first list ... and so on. What I would like to reach, is to applicate function checkIfCorrect (by function try) to all combinations of [Char]s from all lists
([[Char]] ). I mean the following (e.g.): third [Char] on the first list, eighth [Char] on the second list, eleventh [Char] on the third list and so on. Everyone with everyone. How could I easy reach that?
I just wanted to show you an alternative way of writing #WillemVanOnsem's code. I'm guessing that you're a Haskell beginner, so hopefully this answer will give you a tiny glimpse of a rich and beautiful idea which you'll soon be learning about in full as you progress with the language. So don't worry too much if you don't understand everything about this code right away; I'm just trying to give you a taste!
A list comprehension can always be reformulated using the list monad:
import Control.Monad (guard)
try as bs cs = head $ do
a <- as
b <- bs
c <- cs
guard $ checkIfCorrect a b c
return [a,b,c]
I'm using do notation as a special notation for nested loops: for each a in as, for each b in bs, and for each c in cs, we yield [a,b,c] if checkIfCorrect returns True. The translation from list comprehensions is simple: "enumeration" parts of the list comprehension turn into "binds" using <-, "filter"s turn into calls to guard, and "yield"s turn into returns.
In an imperative language like Python you might write it like this:
def try(as, bs, cs):
for a in as:
for b in bs:
for c in cs:
if checkIfCorrect(a, b, c):
yield [a,b,c]
Like politics under the Western neoliberal hegemony, the imperative code gradually marches rightward. "Staircase" code like this actually crops up quite frequently in imperative programming (think of "callback hell" in JS), so monads were invented to help counteract this tendency. They turned out to be so useful that a special syntax was invented for them, namely do-notation.
Yes, you can make it also look more elegant with list comprehension:
try :: [[Char]] -> [[Char]] -> [[Char]] -> [[Char]]
try as bs cs = head [ [a,b,c] | a <- as, b <- bs, c <- cs, checkIfCorrect a b c ]
-- \__ __/ \__________ ____________/ \__________ _______/
-- v v v
-- yield enumeration filter
The code works as follows: the right part of the list comprehension consists out of an "enumeration" part (denoted by the comment section). Since we write a <- as, b <- bs, c <- cs it means that a will take any value from as, and for every such a, b will take any value of bs, etc. So that means every possible combination will be emitted.
Next there is the "filter" phase: there is a predicate checkIfCorrect a b c that will be called and only if that predicate returns True, the result will be "yielded".
On the left side we see "yield". It describes what to add to the list (based on the enumeration) given the filter succeeds. If that happens we add [a,b,c] to that list. If there are multiple such configurations that succeed, we might end up with a list containing multiple solutions. Note however that list comprehension is done lazily: so as long as you do not ask for at least one such element, it will not generate the first element, nor the second, etc.
Now we also need head (in front of the list comprehension). head :: [a] -> a returns the first element of the list. So try will return the first element that satisfies the condition.
While both Willem Van Onsem's and The Orgazoid's answers are good (upvoted), you can also approach part of the problem in a more generalised way, and not only for lists.
For the following, you're going to need these imports:
import Control.Monad (MonadPlus, mfilter)
import Data.Maybe (fromMaybe, listToMaybe)
If I'm understanding the question correctly, you want to try all combinations of as, bs, and cs. You can typically achieve combination-like behaviour with the Applicative typeclass:
combinations = (,,) <$> as <*> bs <*> cs
(,,) is a function that creates triples (three-element tuples) from three individual values.
This works for lists, because lists are applicative:
*Prelude> (,,) <$> [1,2] <*> ["foo", "bar"] <*> [True, False]
[(1,"foo",True),(1,"foo",False),(1,"bar",True),(1,"bar",False),(2,"foo",True),(2,"foo",False),(2,"bar",True),(2,"bar",False)]
but it also works for e.g. Maybes:
*Prelude> (,,) <$> Just 1 <*> Just "foo" <*> Just False
Just (1,"foo",False)
With that, you can now define the core of your function:
try' :: MonadPlus m => ((a, a, a) -> Bool) -> m a -> m a -> m a -> m [a]
try' predicate as bs cs =
tripleToList <$> mfilter predicate combinations
where
combinations = (,,) <$> as <*> bs <*> cs
tripleToList (a, b, c) = [a, b, c]
You'll notice that this helper function is completely generic. It works for any MonadPlus instance of any contained element a.
Here are some examples:
*Answer> try' (const True) ["foo", "bar", "baz"] ["qux", "quux", "quuz", "corge"] ["grault", "garply"]
[["foo","qux","grault"],["foo","qux","garply"],["foo","quux","grault"],["foo","quux","garply"],["foo","quuz","grault"],["foo","quuz","garply"],["foo","corge","grault"],["foo","corge","garply"],["bar","qux","grault"],["bar","qux","garply"],["bar","quux","grault"],["bar","quux","garply"],["bar","quuz","grault"],["bar","quuz","garply"],["bar","corge","grault"],["bar","corge","garply"],["baz","qux","grault"],["baz","qux","garply"],["baz","quux","grault"],["baz","quux","garply"],["baz","quuz","grault"],["baz","quuz","garply"],["baz","corge","grault"],["baz","corge","garply"]]
*Answer> try' (const False) ["foo", "bar", "baz"] ["qux", "quux", "quuz", "corge"] ["grault", "garply"]
[]
*Answer> try' (const True) (Just "foo") (Just "bar") (Just "baz")
Just ["foo","bar","baz"]
*Answer> try' (const False) (Just "foo") (Just "bar") (Just "baz")
Nothing
You should notice that if predicate always returns False, you'll get nothing back. For lists, you get the empty list; for Maybe, you literally get Nothing.
So far it's all generic, but checkIfCorrect isn't. It also looks like you'd like to get only the first elements that match. You can achieve that by composing try' with checkIfCorrect:
try :: [String] -> [String] -> [String] -> [String]
try as bs cs = fromMaybe [] $ listToMaybe $ try' isCorrect as bs cs
where isCorrect (a, b, c) = checkIfCorrect a b c
Here, I've created a private isCorrect function in order to uncurry the checkIfCorrect function. I've then used a combination of listToMaybe and fromMaybe to return the first element of the resulting list. Other answers here use head, but that's going to throw an exception if the list is empty, so I used this combination instead, because it's safe.
I am having a problem with removing an argument 'e' in this function:
numocc e = map length . (map . filter . (==)) e
The function checks the number of occurences of an element inside a two-dimensional list (lists within list). So you call it as follows:
numocc 1 [[1, 2], [2, 3, 2, 1, 1], [3]]
Result : [1,2,0]
Argument e is on the far right on both sides of the equal sign, and is not encased in any parameters. Therefore, I should be able to remove it to get a point-free function:
numocc = map length . (map . filter . (==))
However I get this error:
Type error in application
Expression : map length . map . filter . (==)
Term : map length
Type : [[b]] -> [Int]
Does not match : ([[a]] -> [[a]]) -> [Int]
What is the problem here? Thanks.
Your original function is being parsed as
numocc e = (map length) . ((map . filter . (==)) e)
So you can't just remove the e since it doesn't technically appear at the end of the definition. However, if you define the operator
(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) = (.) . (.)
Then you can write it as
numocc = map length .: (map . filter . (==))
The parentheses on map . filter . (==) are required since you can't mix . and .: due to fixity rules.
However, at this point you're just making this function harder to read and maintain. It would be better to break it down into smaller sections and introduce some intermediate names, along with adding the right type signature and giving the function a better name to start with:
numOccurrences :: Eq a => a -> [a] -> Int
numOccurrences valueToCount values = length (filter (== valueToCount) values)
numOccurrencesInSublists :: Eq a => a -> [[a]] -> [Int]
numOccurrencesInSublists valueToCount = map (numOccurrences valueToCount)
This is far more readable, doesn't rely on fancy operators, and expresses your intent more clearly. Since the case for counting in a single list is a separate function, you can now use it elsewhere too.
Remember, elegant code isn't about making it as short as possible, it's about making it as clear as possible. Descriptive names (not necessarily long ones), explicit arguments, and small, composable units are best.
For an assignment I am working on a list of functions [Int -> Int] (eg. [(+3), (*4), (+1)] ) and I would like to apply a single Int to each of them, in turn creating a list of results [Int]
I already searched a lot, but I am unable to find a way to do such an operation. Using map does not work as I would expect. The related error is this:
ERROR - Cannot infer instance
*** Instance : Num ((Label -> Label) -> a)
As requested the code:
data Tree = Node (Label -> Label) Label [Tree]
type Label = Int
testTree = Node (+1) 3 [ Node (+1) 5 [], Node (+1) 4 [Node (+1) 1 [], Node (+2) 7 []]]
listify :: Tree -> [(Label -> Label)]
listify t = [(getNodeFunction t)] ++ concat(map (listify) (getSubTrees t))
*Main> map (\f -> f 7) (listify testTree)
this actually works. Had a piece of faulty code in the file still, sorry for the fuss.
You can use the $ operator, which stands for function application.
> map ($ 3) [(+3), (*4), (+1)]
[6,12,4]
This basically expands to [(+3) $ 3, (*4) $ 3, (+1) $ 3], which is just function application.
Basically this is an applicative job. You may do like
λ> [(+3), (*4), (+1)] <*> pure 3 -- or [3]
[6,12,4]
You also can use list comprehension for this. This line is enough for your example:
[ f 3 | f <- [(+3), (*4), (+1)] ]
This applies every function in the list on the right hand side to the value (3 in this case) on the left hand side.
For a more general version, this could be helpful:
applyFuns :: [(a->b)] -> a -> [b]
applyFuns fs x = [ f x | f <- fs ]
applyFuns [(+3), (*4), (+1)] 3
The Function applyFuns takes a list of functions from Type a->b as the first and a value of type b as the second. The result is a list of type b that contains the result of every function in the first list applied to the second argument.
If flist is the list of functions and x is the argument, you need map (\f -> f x) flist.
For example
Prelude> map (\f -> f 10) [(4 +), (3 *)]
[14,30]
I know this question is a bit old, but I feel like there oughta be an answer mentioning sequence:
> sequence [(+3), (*4), (+1)] 3
[6,12,4]
(These days, sequenceA is considered the modern replacement for sequence; it has the same behavior whenever both typecheck, but typechecks in slightly more situations. No difference here, though, so I like the slightly less-noisy name for this.)
Wondering if I could get some help writing this function. I am trying to create a function that inverts each "pair" in the list.
module Invert where
invert :: [(a,b)] -> [(b,a)]
invert [(a,b)] = [(b,a)]
When I enter invert [(3,1) (4,1) (5,1)]... it is supposed to give me [(1,3) (1,4) (1,5)... But it gives me...
*Invert> [(3,1) (4,1) (5,1)]
<interactive>:2:2:
The function `(3, 1)' is applied to two arguments,
but its type `(t0, t1)' has none
In the expression: (3, 1) (4, 1) (5, 1)
In the expression: [(3, 1) (4, 1) (5, 1)]
In an equation for `it': it = [(3, 1) (4, 1) (5, 1)]
Since lists are recursive data structures, you have to process a list recursively in order to swap all its elements, or use some higher order function that does the processing for you. If you define
invert [(a,b)] = [(b,a)]
it will only convert single-element lists, all other inputs will fail with an error!
Try to think about the input invert gets: It's either an empty list, or a non-empty lists. In the case of a non-empty list, you can swap the first element and convert the rest recursively.
(If you don't want to invert invert yourself, just use
invert = map swap
where swap is from Data.Tuple.)
Best way to solve this: split it into smaller problems, and either find library functions that solve those, or write your own. I always tell beginners that this is a superior exercise than trying to write a function like invert in just one part, because you should be learning the following three things:
How to split a problem into small, reusable pieces.
The standard library functions offered by the language.
How to use recursion to write small, reusable functions like the ones in the standard library.
In this case, we can split the problem into:
Inverting an individual tuple.
Applying a function to all elements of a list, and collecting the list of results.
The second one is just the common map function on lists, which comes with the standard library. You could try writing your own version of it; this sort of thing is always a good exercise for a beginner:
map :: (a -> b) -> [a] -> [b]
map f [] = ...
map f (x:xs) = ...
The first, as Petr points out, is the swap function from Data.Tuple. But we can write our own easily:
swap :: (a, b) -> (b, a)
swap (a, b) = (b, a)
And now, of course:
invert :: [(a, b)] -> [(b, a)]
invert = map swap
So you want to map a function over the list that's of type (a, b) -> (b, a). The function (,) has type b -> a -> (b,a). So if we flip it, we get a -> b -> (b, a). Now if we uncurry that, we get (a, b) -> (b, a):
invert = map (uncurry $ flip (,))
E.g.
> map (uncurry $ flip (,)) [(1, "a"), (2, "b")]
[("a",1),("b",2)]
As an aside, your patten matching doesn't match what you want. The definition
invert [(a,b)] = [(b,a)]
says "match a list with a single tuple in it". If you have a list with multiple tuples, the match will fail. Also, as Josh Lee pointed out, you need commas between tuples in your list.