I am learning about monads from the book 'Learn You a Haskell for Great Good!' by Miran Lipovaca. I am trying to understand the associativity law for monads. Essentially, the law states that when you have a chain of monadic function applications with >>=, it shouldn't matter how they're nested.
The following code enables one to pass the result of a function of type a -> m b to a function of type b -> m c:
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = (\x -> g x >>= f)
However, for the example below:
ghci> let f x = [x, -x]
ghci> let g x = [x*3, x*2]
ghci> let h = f <=< g
ghci> h 3
[9, -9, 6, -6]
Are f x and g x both functions? It seems to be that they are lists with different values of x and not functions. How does the line let h = f <=< g work in the above code? f and g have to be functions since they are used with <=< but I am not sure what they are.
f x = [x, -x]
This is ordinary function definition syntax. We are defining a new function f, by writing down what it would produce when applied to a hypothetical value x.
let (whether as a statement or a let ... in ... expression) just introduces a block where you can make definitions, much like where. The definitions themselves use the same syntax as global ones do.
If you know how to define functions by writing e.g. plusOne n = n + 1 in a file, then this syntax is exactly the same (if you don't know how to do that, then I'd suggest reading through some introductory tutorials on fundamental Haskell syntax before you try to understand monadic function composition).
So after those definitions f and g are functions. f x and g x don't really make sense, since you don't have an x in scope to apply them to.
If you did have such a value in scope, then f x would be an expression that evaluates to a list, which involves calling the function f. It still wouldn't be true to say that f x or g x are functions.
So now it should be clear that let h = f <=< g is defining a new value h by applying the <=< operator to f and g.
Nothing's better for gaining a feeling of understanding, like working through the definitions by hand on a sheet of paper.
f x = [x, -x] can also be written f = (\ x -> [x, -x]). Thus
h 3
= {- by def of h -}
(f <=< g) 3
= {- by def of (<=<) -}
(\x -> g x >>= f ) 3
= {- by defs of f and g -}
(\x -> (\ x -> [x*3, x*2]) x >>= (\ x -> [x, -x])) 3
= {- by substitution -}
(\ x -> [x*3, x*2]) 3 >>= (\ x -> [x, -x])
= {- by substitution -}
[3*3,
3*2] >>= (\ x -> [x, -x])
= {- by definition of (>>=) for [] -}
concat [ (3*3) & (\ x -> [x, -x]) -- x & f == f x
, (3*2) & (\ x -> [x, -x])
]
= {- by definition of concat -}
(3*3) & (\ x -> [x, -x])
++ (3*2) & (\ x -> [x, -x])
=
[9, -9, 6, -6]
(edit) For a picture, and some more discussion of these Kleisli arrows and their composability, see this older answer of mine.
Related
So I am currently trying to figure out how to write a function where it takes 2 lists of equal lengths and multiplies the same position of both lists through folding, and returns the result as a new List.
eg) let prodList [1; 2; 3] [4; 5; 6] ;;
==> (through folding) ==> [1*4; 2*5; 3*6]
==> result = [4; 10; 18]
I feel like I need to use List.combine, since it will put the values that need to be multiplied into tuples. After that, I can't figure out how to break apart the tuple in a way that allows me to multiply the values. Here is what I have so far:
let prodLists l1 l2 =
let f a x = (List.hd(x)) :: a in
let base = [] in
let args = List.rev (List.combine l1 l2) in
List.fold_left f base args
Am I on the right track?
You can use fold_left2 which folds two lists of the same length. The documentation can give you more details (https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html):
val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
List.fold_left2 f a [b1; ...; bn] [c1; ...; cn] is f (... (f (f a b1 c1) b2 c2) ...) bn cn. Raise Invalid_argument if the two lists are determined to have different lengths.
Another way is to fold the output of combine as you have suggested, I would recommend you to try it by yourself before looking at the solution bellow.
Solution:
let prod_lists l s =
List.rev (List.fold_left2 (fun acc a b -> (a * b) :: acc) [] l s);;
let prod_lists' l s =
List.fold_left (fun acc (a, b) -> (a * b) :: acc) [] (List.rev (List.combine l s));;
First let me note using fold to implement this operation seems a bit forced, since you have to traverse both lists at the same time. Fold however combines the elements of a single list. Nonetheless here is an implementation.
let e [] = []
let f x hxs (y::ys) = (x*y) :: hxs ys
let prodList xs ys = List.fold_right f xs e ys
Looks a bit complicated, so let me explain.
Universal Property of fold right
First you should be aware of the following property of fold_right.
h xs = fold_right f xs e
if and only if
h [] = e
h (x::xs) = f x (h xs)
This means that if we write the multiplication of lists in the recursive form below, then we can use the e and f to write it using fold as above. Note though we are operating two lists so h takes two arguments.
Base case - empty lists
Multiplying two empty lists returns an empty list.
h [] [] = []
How to write this in the form above? Just abstract over the second argument.
h [] = fun [] -> []
So,
e = fun [] -> []`
Or equivalently,
e [] = []
Recursive case - non-empty lists
h (x::xs) (y::ys) = x*y :: h xs ys
Or, using just one argument,
h (x::xs) = fun -> (y::ys) -> x*y :: h xs ys
Now we need to rewrite this expression in the form h (x::xs) = f x (h xs). It may seem complicated but we just need to abstract over x and h xs.
h (x::xs) = (fun x hxs -> fun (y::ys) -> x*y :: hxs ys) x (h xs)
so we have that f is defined by,
f = fun x hxs -> fun (y::ys) -> x*y :: hxs ys
or equivalently,
f x hxs (y::ys) = x*y :: hxs ys
Solution as a fold right
Having determined both e and f we just plug then into fold according to the first equation of the property above. And we get,
h xs = List.fold_right f xs e
or equivalently,
h xs ys = List.fold_right f xs e ys
Understanding the implementation
Note that the type of List.fold_right f xs e is int list -> int list, so the fold is building a function on lists, that given some ys will multiply it with the given parameter xs.
For an empty xs you will expect an empty ys and return an empty result so,
e [] = fun [] -> []
As for the recursive case, the function f in a fold_right must implement a solution for x::xs from a solution for xs. So f takes an x of type int and a function hxs of type int list -> int list which implements the multiplication for the tail, and it must implement multiplication for x::xs.
f x hxs = fun (y::ys) -> x*y :: hxs ys
So f constructs a function that multiplies x with y, and then applies to ys the already constructed hxs which multiplies xs to a list.
You mostly have the right idea; you'll want to combine (zip in other languages) the two lists and then map over each tuple:
let prod_lists l1 l2 =
List.combine l1 l2
|> List.map (fun (a, b) -> a * b)
The key is that you can pattern match on that tuple using (a, b).
You can also fold over the combined list, then rev the result, if you don't want to use map.
So what I have so far is something like this:
combs :: [[Char]]
combs = [[i] ++ [j] ++ [k] ++ [l] | i <- x, j <- x, k <- x, l <- x]
where x = "abc"
So this is the working function for n = 4, is there any way to make this work for an arbitrary number of generators? I could program in for n = 1, 2, 3 etc.. but ideally need it to work for any given n. For reference, x is just an arbitrary string of unique characters. I'm struggling to think of a way to somehow extract it to work for n generators.
You can use replicateM:
replicateM :: Applicative m => Int -> m a -> m [a]
E.g.:
generate :: Num a => Int -> [[a]]
generate = flip replicateM [1,2,3]
to generate all possiible lists of a given length and consisting of elements 1..3.
As far as I know, you can not construct list comprehension with an arbitrary number of generators, but usually if you do something with arbitrary depth, recursion is the way to do it.
So we have to think of solving this, in terms of itself. If you want all possible strings that can be generated with the characters in x. In case n = 0, we can generate exactly one string: the empty string.
combs 0 = [""]
so a list with one element [].
Now in case we want to generate strings with one characters, we can of course simply return x:
combs 1 = x
and now the question is what to do in case n > 1. In that case we can obtain all the strings with length n-1, and and for each such string, and each such character in x, produce a new string. Like:
combs n = [ (c:cs) | c <- x, cs <- combs (n-1) ]
Note that this makes the second case (n = 1) redundant. We can pick a character c from x, and prepend that to the empty string. So a basic implementation is:
combs :: Int -> [[Char]]
combs 0 = [""]
combs n = [(c:cs) | c <- x, cs <- combs (n-1)]
where x = "abc"
Now we can still look for improvements. List comprehensions are basically syntactical sugar for the list monad. So we can use liftA2 here:
import Control.Applicative(liftA2)
combs :: Int -> [[Char]]
combs 0 = [""]
combs n = liftA2 (:) x (combs (n-1))
where x = "abc"
we probably also want to make the set of characters a parameter:
import Control.Applicative(liftA2)
combs :: [Char] -> Int -> [[Char]]
combs _ 0 = [""]
combs x n = liftA2 (:) x (combs (n-1))
and we do not have to restrict us to characters, we can produce a certesian power for all possible types:
import Control.Applicative(liftA2)
combs :: [a] -> Int -> [[a]]
combs _ 0 = [[]]
combs x n = liftA2 (:) x (combs (n-1))
First I would translate the comprehension as a monadic expression.
x >>= \i -> x >>= \j -> x >>= \k -> x >>= \l -> return [i,j,k,l]
With n = 4 we see we have 4 x's, and generally will have n x's. Therefore, I am thinking about a list of x's of length n.
[x,x,x,x] :: [[a]]
How might we go from [x,x,x,x] to the monadic expression? A first good guess is foldr, since we want to do something with each element of the list. Particularly, we want to take an element from each x and form a list with these elements.
foldr :: (a -> b -> b) -> b -> [a] -> b
-- Or more accurately for our scenario:
foldr :: ([a] -> [[a]] -> [[a]]) -> [[a]] -> [[a]] -> [[a]]
There are two terms to come up with for foldr, which I will call f :: [a] -> [[a]] -> [[a]] and z :: [[a]]. We know what foldr f z [x,x,x,x] is:
foldr f z [x,x,x,x] = f x (f x (f x (f x z)))
If we add parentheses to the earlier monadic expression, we have this:
x >>= \i -> (x >>= \j -> (x >>= \k -> (x >>= \l -> return [i,j,k,l])))
You can see how the two expressions are looking similar. We should be able to find an f and z to make them the same. If we choose f = \x a -> x >>= \x' -> a >>= \a' -> return (x' : a') we get:
f x (f x (f x (f x z)))
= (\x a -> a >>= \a' -> x >>= \x' -> return (x' : a')) x (f x (f x (f x z)))
= f x (f x (f x z)) >>= \a' -> x >>= \x' -> return (x' : a')
= f x (f x (f x z)) >>= \a' -> x >>= \l -> return (l : a')
= (f x (f x z) >>= \a' -> x >>= \k -> return (k : a')) >>= \a' -> x >>= \l -> return (l : a')
= f x (f x z) >>= \a' -> x >>= \k -> x >>= \l -> return (l : k : a')
Note that I have reversed the order of i,j,k,l to l,k,j,i but in context of finding combinations, this should be irrelevant. We could try a' ++ [x'] instead if it was really of concern.
The last step is because (a >>= \b -> c) >>= \d -> e is the same as a >>= \b -> c >>= \d -> e (when accounting for variable hygiene) and return a >>= \b -> c is the same as (\b -> c) a.
If we keep unfolding this expression, eventually we will reach z >>= \a' -> … on the front. The only choice that makes sense here then is z = [[]]. This means that foldr f z [] = [[]] which may not be desirable (preferring [] instead). Instead, we might use foldr1 (for non-empty lists, and we might use Data.NonEmpty) or we might add a separate clause for empty lists to combs.
Looking at f = \x a -> x >>= \x' -> a >>= \a' -> return (x' : a') we might realise this helpful equivalence: a >>= \b -> return (c b) = c <$> a. Therefore, f = \x a -> x >>= \x' -> (x' :) <$> a. Then also, a >>= \b -> c (g b) = g <$> a >>= \b -> c and so f = (:) <$> x >>= \x' -> x' <$> a. Finally, a <*> b = a >>= \x -> x <$> b and so f = (:) <$> x <*> a.
The official implementation of sequenceA for lists is foldr (\x a -> (:) <$> x <*> a) (pure []), exactly what we came up with here too. This can be further shortened as foldr (liftA2 (:)) (pure []) but there is possibly some optimisation difference that made the implementors not choose this.
Last step is to merely come up with a list of n x's. This is just replicate replicate n x. There happens to be a function which does both replication and sequencing, called replicateM replicateM n x.
I have written a function:
let rec addAll f l =
match l with
| [] -> 0
| [x] -> x
| hd::tl -> let combined = addAll f tl in
f (hd) combined
;;
I works as titled, it will add all the elements of a list. However, I want to write this program so it is Left associative, so instead of combining the elements [1;2;3] as 1 - (2 - 3), I want it to be: (1 - 2) - 3.
Any hints on how I can make this forward recursive instead of tail? Or how can I make it so this function works as I intend? I know I could just reverse the list, but I want to try another way.
Your code does a right fold. Roughly speaking, it's like this:
let addAll f l = List.fold_right f l 0
You want to change it to a left fold. Roughly speaking you want this:
let addAll f l = List.fold_left f 0 l
Or, slightly more accurately you want:
let addAll f = function
| [] -> 0
| h :: t -> List.fold_left f h t
This second function does seem to do what you want:
# addAll (-) [1;2;3];;
- : int = -4
If you want to write it from scratch (not using List.fold_left), the easiest way is with an accumulator:
let addAllScratch f l =
let rec iadd f accum l =
match l with
| [] -> accum
| a::l -> iadd f (f accum a) l
in
match l with
| [] -> 0
| h :: t -> iadd f h t
This does do what you want:
# addAllScratch (-) [1;2;3];;
- : int = -4
(In essence, I just inserted the standard definition of List.fold_left into the code.)
let rec addAll f l =
match l with
| [] -> 0
| [x] -> x
| x::y::tl -> addAll f ((f x y)::tl)
;;
Test
# addAll (fun a b -> Printf.printf "(%d %d)" a b; a+b) [1;2;3];;
(1 2)(3 3)- : int = 6
I cant understand some things in my code. It is program in OCaml which generates all distinct pairs from elements in list. Here's my code:
let rec tmp f list x =
match list with
| [] -> x
| h :: t -> f h (tmp f t x);;
(* ^ ^ (^ ) (1) *)
let rec distinctpairs lst =
match lst with
| [] -> []
| h :: t -> tmp ( fun x lt -> (h,x)::lt) t (distinctpairs t);;
(* ^ ^ (2) *)
Do function tmp returns three values ?
How i can give an argument to func, when i dont know what is x?
When i assume that tmp return three values, that why when I giving as arg to tmp the ( fun x lt -> (h,x)::lt) argument, and it works?
1. Do function tmp returns three values ?
let rec tmp f list x =
match list with
| [] -> x
| h :: t -> f h (tmp f t x);;
The simple answer to this question is no.
f h (tmp f t x) is not three value, instead, it is a function execution/application on f.
2. How i can give an argument to func, when i dont know what is x?
let rec distinctpairs lst =
match lst with
| [] -> []
| h :: t -> tmp ( fun x lt -> (h,x)::lt) t (distinctpairs t);;
The truth here is you know x. x is defined as a parameter of the anonymous function fun x lt -> (h, x)::lt.
When i assume that tmp return three values, that why when I giving as arg to tmp the ( fun x lt -> (h,x)::lt) argument, and it works?
First of all, when ocaml sees tmp f list x, ocaml does not know anything but tmp accepts 3 parameters.
When ocaml reaches | [] -> x, it knows whatever type x is, the tmp will return the same type as x.
When ocaml reaches | h::t -> f h (tmp f t x), it knows f must be a function and f will have 2 parameters: one with type of h and one with type of x
Then in your distinctpairs function, ( fun x lt -> (h,x)::lt) is an anonymous function which really matches the prediction above.
A better way to write the two functions:
let rec tmp f x = function
| [] -> []
| h :: t -> f h (tmp f x t)
let rec distinctpairs = function
| [] -> []
| h :: t -> tmp (fun x lt -> (h,x)::lt) (distinctpairs t) t
I also suggest you to read Real World Ocaml book. It is the newest and most comprehensive book on OCaml and it is good.
When you try to enter functional programming world, there is no shortcut. It is not like you learn Spanish as an English speaker. It is more like learning Chinese/Japanese as an English speaker.
The whole idea is quite different from Java or C# or C, and of course, much better than Java (my personal feeling). So I suggest you to learn from ground.
Is there a way to change the order from left-associative to right-associative, except parentheses? For example in Haskell you can write foo $ bar b and foo will be applied to a result from bar b.
let a x = x * 4;;
let b y = y + 2;;
let c = a ??? b 3;;
print_int c;;
Should print 20
Sure, you can define it yourself:
let (###) f x = f x
Then, a ### b 3 evaluates to 20. Make sure to select a starting symbol such that it is right-associative (see here) ($... is left-associative)
You just have to define a symbol for such applications:
let (###) f x = f x ;;
And then
let f x = x * 4;;
let g y = y + 2;;
let a = f ### g 3;;
print_int a;;
does print 20.
Note that the next version of OCaml (3.13 or 4.00) will provide builtin primitives for applications that avoid creating intermediate partially applied functions:
external (###) : ('a -> 'b) -> 'a -> 'b = "%apply"
external (|>) : 'a -> ('a -> 'b) -> 'b = "%revapply"
The last one is the opposite of %apply:
print_int (3 |> g |> f);;
Note that you cannot use ($) as it is left-associative in the definition of the OCaml parser:
let ($) f x = f x ;;
let a = f $ g 3;; (* ok ! ??? *)
let a = f $ g $ g 3;; (* ERROR -> g is not an integer,
because OCaml computes (f $ g) first *)