F# - Same Function With Different Parameters - function

In F#, is it possible for a function to take one required parameter and one or more optional parametes depending on context? In the following toy example, whisk initially takes eggYolks as its only parameter but, in the very next step, it takes the output of the initial step plus granulatedSugar and marsalaWine. Is this possible and how do I feed the additional ingredients to tiramisu and print out both steps to the console?
module Tiramisu =
// http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html
open System
// Ingredients.
let eggYolks = "70<g> of egg yolks."
let granulatedSugar = "100<g> of granulated sugar."
let marsalaWine = "120<ml> of sweet marsala wine."
let whisk ingredient = printf "Whisk %s\t" ingredient
let tiramisu ingredients =
ingredients
|> whisk // eggYolks only.
// |> whisk // plus granulatedSugar and marsalaWine.
[<EntryPoint>]
tiramisu eggYolks
// tiramisu (eggYolks granulatedSugar marsalaWine)

Summary: You should write whisk to take a list. See below for the full explanation, which starts with the wrong approach, explains why it's the wrong approach, and then moves to the right approach.
Long explanation:
The question you're asking is whether you could write the function whisk to take multiple things to be whisked, e.g. you're asking whether a whisk function could look like:
let whisk item1 maybeItem2 maybeItem3 =
printfn "Whisking %A" item1
match maybeItem2 with
| None -> ()
| Some item -> printfn "Also whisking %A" item
match maybeItem3 with
| None -> ()
| Some item -> printfn "Also whisking %A" item
But this design has some problems. For one thing, this function's type signature is inconvenient: the first parameter is an ingredient, but the second and third parameters might be ingredients (they're actually Options). In other words, if you had specified the types of the parameters in your function, they would have looked like:
type Ingredient = string // For this example
let whisk (item1 : Ingredient) (maybeItem2 : Ingredient option) (maybeItem3 : Ingredient option) =
// ... function body goes here ...
Why is this inconvenient? Well, if you only wanted to whisk a single thing, you'd have to call this function as whisk eggYolks None None. (Calling it without the two None parameters would get you a partially-applied function, which is a different topic). And another inconvenience: this is limited to just three items; if you wanted to whisk four items, you'd have to change the function signature, and then you'd have to change everywhere it was called to pass four parameters by adding an extra None to each call.
Also, this example function doesn't actually return anything, for simplicity. If it did return something, it gets even more complicated. For example, if you're coming from an imperative language like C#, you might try writing this:
type Ingredient = string // For this example
let whisk (item1 : Ingredient) (maybeItem2 : Ingredient option) (maybeItem3 : Ingredient option) =
printfn "Whisking %A" item1
let mutable mixtureSoFar = item1
match maybeItem2 with
| None -> ()
| Some item ->
printfn "Also whisking %A" item
mixtureSoFar <- mixtureSoFar + item
match maybeItem3 with
| None -> ()
| Some item ->
printfn "Also whisking %A" item
mixtureSoFar <- mixtureSoFar + item
mixtureSoFar
But that's ugly. When your F# code starts looking ugly, that's usually a sign that your design is off, somehow. For example, maybe you could let the whisk function take a list of ingredients, instead of trying to pass multiple parameters where some of them might be None. E.g., the whisk function would instead look like:
let whisk (items : Ingredient list) =
// ... function body goes here ...
And then you'd call it like this:
let whiskedEggYolks = whisk [eggYolks]
let mixture = whisk [whiskedEggYolks; granulatedSugar; marsalaWine]
What would that function look like inside? Well, it would probably apply some transformation to each ingredient, then some combining function to combine all those ingredients together into a single result. In F#, "apply some transformation to each item" is called map, and "apply some combining function to combine multiple items into a single one" is either fold or reduce. (I'll explain the difference between fold and reduce below). Here, I think you'd want reduce, since whisking an empty bowl doesn't make sense. So our whisk function becomes:
let whisk (ingredients : Ingredient list) =
ingredients
|> List.map (fun x -> sprintf "%s, whisked" x)
|> List.reduce (fun a b -> sprintf "%s, plus %s" a b)
When you whisk "70<g> of egg yolks", you get "70<g> of egg yolks, whisked". Then when you whisk that together with "100<g> of granulated sugar" and "120<ml> of sweet marsala wine", you get the output:
"70<g> of egg yolks, whisked, plus 100<g> of granulated sugar, whisked, plus 120<ml> of sweet marsala wine, whisked"
And yet your function is beautifully simple (just three lines to handle any number of ingredients!) and you didn't have to write any of the list-handling code, since that was taken care of by the standard F# core library functions List.map and List.reduce. That sort of elegance is what you should be aiming for when you do functional programming.
Fold and reduce
I said I'd explain the difference between fold and reduce. The main difference is whether you expect to be dealing with empty collections sometimes. The reduce function requires that there be at least one item in the collection you're reducing, and doesn't need an initial value since the first item of the collection is taken as the initial value. But because reduce needs the first item of the collection to set its initial value, it will throw an exception if it is passed an empty collection, because there's no way for it to know what value to use. (F# deliberately avoids null, for good reason -- so it's not always possible to determine a good value for an empty collection). Whereas fold requires you to specify an explicit initial value, but it is okay with an empty collection, because if you pass an empty collection then it just returns the default value. E.g.,
let zeroInts = []
let oneInt = [1]
let twoInts = [1; 2]
let add x y = x + y
zeroInts |> List.reduce add // Error
oneInt |> List.reduce add // Result: 1
twoInts |> List.reduce add // Result: 3
zeroInts |> List.fold add 0 // No error, result: 0
oneInt |> List.fold add 0 // Result: 1
twoInts |> List.fold add 0 // Result: 3
See also Difference between fold and reduce? for more explanations.

Related

Filter list of tuples to output list using a conditional

I want to use the standard Prelude in Haskell (no recursion, no list comprehension) to filter a list of tuples and then output a list of integers. It should check a list of 3-tuples that contain integers, e.g.,
[(1,2,3), (2,3,7), (4,5,20)]
and see if the sum of element #1 and #2 equals element #3. If it does, put element #3 in the list and then output the list. This is the output that I am looking for:
>sumOfElements [(1,2,3), (2,3,7), (4,5,9)]
[3,9]
This is what I have tried:
sumsOfElements :: [(Int, Int, Int)] -> [Int]
sumsOfElements list = filter (\(a,b,c) -> a+b==c) list
This kind of works but it outputs a list of tuples that meets the conditional.
>sumOfElements [(1,2,3), (2,3,7), (4,5,9)]
[(1,2,3), (4,5,9)]
I'm not sure how to take c from the tuple and append that element to a new list for the output.
Think about this as a pipeline: first find the right elements, then transform them into the shape you need:
sumOfElements = map (\(_,_,c) -> c) . filter (\(a,b,c) -> a+b==c)
And trust that laziness and optimizations (specifically, foldr/build fusion) will make it performant.
You can do this more succinctly with a list comprehension:
sumOfElements list = [c | (a,b,c) <- list, a+b==c]

How to access the elements in the set returned by an Alloy function?

I have an Alloy function in my model like:
fun whichFieldIs[p:Program, fId:FieldId, c:Class] : Field{
{f:Field | f in c.*(extend.(p.classDeclarations)).fields && f.id = fId}
}
This function is working in my model and can return a set of elements such as:
{Field$0, Field$1}
although the function return is not "set Field". I already saw this through the Alloy evaluator tool (available in alloy4.2.jar). What i am trying to do is getting the first element of this set in another predicate, for instance:
pred expVarTypeIsOfA[p:Program, exprName:FieldId, mClass:Class, a:ClassId]{
let field = whichFieldIs[p, exprName, mClass],
fieldType = field[0].type
{
...
}
}
Even when i change the return of the function to "set Field", the error "This expression failed to be typechecked" appears. I only want to get the first element of a set returned by a function, any help?
Does the order really matter in that case? If so, you should take a look at this: seq
In the following example, for each person p, "p.books" is a sequence
of Book:
sig Book { }
sig Person {
books: seq Book
}
...So if s is a sequence of Book, then the first element is s[0]...
seq is now a reserved word, but is nothing more than a relation Int -> Elem.
If it does not matter, you could use an adequate quantifier, e.g.:
pred expVarTypeIsOfA[p:Program, exprName:FieldId, mClass:Class, a:ClassId]{
some field: whichFieldIs[p, exprName, mClass] | {
field.type ...
}
}

Counting occurrences of a list item from a list?

(See edit at the bottom of this post)
I'm making a program in Elixir that counts the types of HTML tags from a list of tags that I've already obtained. This means that the key should be the tag and the value should be the count.
e.g. in the following sample file
<html><head><body><sometag><sometag><sometag2><sometag>
My output should be something like the following:
html: 1
head: 1
body: 1
sometag: 3
sometag2: 1
Here is my code:
def tags(page) do
taglist = Regex.scan(~r/<[a-zA-Z0-9]+/, page)
dict = Map.new()
Enum.map(taglist, fn(x) ->
tag = String.to_atom(hd(x))
Map.put_new(dict, tag, 1)
end)
end
I know I should be probably using Enum.each instead but when I do that my dictionary ends up just being empty instead of incorrect.
With Enum.map, this is the output I receive:
iex(15)> A3.test
[%{"<html" => 1}, %{"<body" => 1}, %{"<p" => 1}, %{"<a" => 1}, %{"<p" => 1},
%{"<a" => 1}, %{"<p" => 1}, %{"<a" => 1}, %{"<p" => 1}, %{"<a" => 1}]
As you can see, there are duplicate entries and it's turned into a list of dictionaries. For now I'm not even trying to get the count working, so long as the dictionary doesn't duplicate entries (which is why the value is always just "1").
Thanks for any help.
EDIT: ------------------
Okay so I figured out that I need to use Enum.reduce
The following code produces the output I'm looking for (for now):
def tags(page) do
rawTagList = Regex.scan(~r/<[a-zA-Z0-9]+/, page)
tagList = Enum.map(rawTagList, fn(tag) -> String.to_atom(hd(tag)) end)
Enum.reduce(tagList, %{}, fn(tag, acc) ->
Map.put_new(acc, tag, 1)
end)
end
Output:
%{"<a": 1, "<body": 1, "<html": 1, "<p": 1}
Now I have to complete the challenge of actually counting the tags as I go...If anyone can offer any insight on that I'd be grateful!
First of all, it is not the best idea to parse html with regexes. See this question for more details (especially the accepted answer).
Secondly, you are trying to write imperative code in functional language (this is about first version of your code). Variables in Elixir are immutable. dict will always be an empty map. Enum.map takes a list and always returns new list of the same length with all elements transformed. Your transformation function takes an empty map and puts one key-value pair into it.
As a result you get a list with one element maps. The line:
Map.put_new(dict, tag, 1)
doesn't update dict in place, but creates new one using old one, which is empty. In your example it is exactly the same as:
%{tag => 1}
You have couple of options to do it differently. Closest approach would be to use Enum.reduce. It takes a list, an initial accumulator and a function elem, acc -> new_acc.
taglist
|> Enum.reduce(%{}, fn(tag, acc) -> Map.update(acc, tag, 1, &(&1 + 1)) end)
It looks a little bit complicated, because there are couple of nice syntactic sugars. taglist |> Enum.reduce(%{}, fun) is the same as Enum.reduce(taglist, %{}, fun). &(&1 + 1) is shorthand for fn(counter) -> counter + 1 end.
Map.update takes four arguments: a map to update, key to update, initial value if key doesn't exist and a function that does something with the key if it exists.
So, those two lines of code do this:
iterate over list Enum.reduce
starting with empty map %{}
take current element and map fn(tag, acc) and either:
if key doesn't exist insert 1
if it exists increment it by one &(&1 + 1)

Retrieve the actual value from json

I have code that parses json:
(Aeson.Object jsonObj) -> case (HashMap.lookup "one" jsonObj, HashMap.lookup "two" jsonObj, , HashMap.lookup "three" jsonObj) of
(Just one, Just two, Just three) -> -- what's next?
_ -> error "All three keys don't exist
"
How do I retrieve the actual values from "one", "two" and "three"? All the three are Data.Aeson.Value and its data type is defined as following but yet I can't figure out what to do next:
data Value Source
A JSON value represented as a Haskell value.
Constructors
Object !Object
Array !Array
String !Text
Number !Number
Bool !Bool
Null
You can check if the values are of the expected type right in the pattern matching like this:
case HashMap.lookup "one" jsonObj of
(Just (Aeson.String t)) -> -- do with string t what pleases you
_ -> error "key not present or not a string"
You could adapt this to the triple in your code or leave it as a separate function, whatever you see fit. But be aware that this style would really mean that you're not using the Parser monad Aeson offers, which is really nice to dissect arbitrary JSON. Assume in your example above, what you really want to achieve is something like this:
parseTriple :: ByteString -> Maybe (Text, Integer, Bool)
then, using parseEither, this can be expressed as simple as
parseTriple bs = decode bs >>= parseMaybe $ \o -> do
one <- o .: "one"
two <- o .: "two"
three <- o .: "three"
return (one, two, three)
I think this nicely expresses what you're doing with the JSON and is easy to follow and maintain. Also, if you don't use parseMaybe but parseEither, you even get kind-of-useful error messages for free.

Haskell use of map and composed function

Ok, I can't figure this one out even though I have an idea what it's doing...
let t = ["APE", "MONKEY", "DONKEY"]
Now consider three cases:
map (length.group) t
(map length.group) t
map (map length.group) t
This returns these three answers:
[3,6,6]
[1,1,1]
[[1,1,1],[1,1,1,1,1,1],[1,1,1,1,1,1]]
Now, can someone explain to me in details what's going on. A crucial part of this question is that I assume that map needs a list to work on and I don't see two maps being passed in the third case for example.
map (length.group) t
This composes the functions length and group. The result is a function that takes a list (string) and returns the number of "groups" in that list (where a group is a sequence of the same character repeating 1 or more times, so "abc" contains 3 groups and so does "aabbcc").
This function is then applied to each string in t using map.
(map length.group) t
Here the function map length (which takes the length of each sublist in a list of lists) is composed with the function group and the composed function is applied to t. In other words it's the same as map length (group t).
map (map length.group) t
Here the function map length . group is applied to each string in t, i.e. map length (group str) is calculated for each string str in t.
Try removing the "length." from all your cases, and see if that helps answer your question. It'll simplify the problem and the answer might show you a little better what's going on.
Or, factoring the third one, it becomes
map (map length.group) ["APE", "MONKEY", "DONKEY"]
--make parse order explicit
map ((map length) . group) ["APE", "MONKEY", "DONKEY"]
--do mapping
[((map length) . group) "APE", ((map length) . group) "MONKEY", ((map length) . group) "DONKEY"]
--use (f.g) x == f (g x)
[(map length) (group "APE"), ...]
[(map length) ["A", "P", "E"], ...]
[[1, 1, 1], ...]
Also try using some animals like "EEL" or "BEE" or "LLAMA" to see anything other than 1's in the final result.