I'm new to F#, apologies if I'm missing something obvious here.
I have the following code, with the intent to get user input and convert it to a uint:
let println ln =
printfn "%s" ln
let rec getUserKeyInput =
let x = System.Console.ReadKey()
string x
let getInputWithPrompt prompt =
println prompt
getUserKeyInput
let rec getUserUIntFromStr str =
try
let i = str |> uint
i
with
| :? System.FormatException -> println "Please enter a positive integer";
(getUserUIntFromStr (getUserKeyInput))
When getUserUIntFromStr is called with let i = getUserUIntFromStr str "Please enter a positive integer" is printed infinitely. I've also tried Console.ReadLine() and stdin.ReadLine(), both in interactive and from main, with the same results. It looks to me like none of the "Read" functions are waiting for input, but that doesn't seem right and I'm guessing I've done something wrong. Any suggestions?
getUserKeyInput is a value, not a function. It's evaluated only once at init time, not every time you reference it.
To make it a function, you need to give it a parameter. What type of parameter? Well, technically any type will do, but F# has you covered: for situations where you need to have some value, but there isn't a sensible value to use (which happens surprisingly often), there is a special type unit with a single value denoted as parentheses ():
let getUserKeyInput () =
let x = System.Console.ReadKey()
string x
(also note that rec is unnecessary, because the function isn't actually recursive)
(also note that ReadKey takes such parameter as well - it's the same deal there)
And then pass the parameter to call the function:
println "Please enter a positive integer"
getUserUIntFromStr (getUserKeyInput ())
Related
The following code comes from Stylish F# 6: Crafting Elegant Functional Code for .NET 6 listing 9-13:
let randomByte =
let r = System.Random()
fun () ->
r.Next(0, 255) |> byte
// E.g. A3-52-31-D2-90-E6-6F-45-1C-3F-F2-9B-7F-58-34-44-
for _ in 0..15 do
printf "%X-" (randomByte())
printfn ""
The author states, "Although we call randomByte() multiple times, only one System.Random() instance is created."
I understand randomByte returns a function that does not create a System.Random() instance, but it seems to me multiple System.Random() instances would be created each time through the for-do-loop anyway.
I would appreciate an explanation of how multiple instances of System.Random() are not created in this case.
The key point is that randomByte is not a function. It's a value with some complex initialization logic. Like, for example, I could write:
let x = 5
Or I could write:
let x =
let fourtyTwo = 42
let thirtySeven = 37
fourtyTwo - thirtySeven
And these would be equivalent. Both declare a value named x and equal to 5. I hope you can see how the expression fourtyTwo - thirtySeven is evaluated only once, not every time somebody gets the value of x.
And so it works with randomByte too: it's a value with non-trivial initialization logic. During that value's initialization, first it creates an instance of System.Random, and then it creates an anonymous function that closes over that instance, and this anonymous function becomes the value of randomByte.
This question is extended from my previous question, about mutable value. I'm pretty sure that the main topic of this question, pre-computation has many things to do with the linked question.
Please see below examples, which I have brought from the book I'm studying with:
let isWord (words : string list) =
let wordTable = Set.ofList words // Expensive computation!
fun w -> wordTable.Contains(w)
val isWord : words:string list -> (string -> bool)
Which accept an string list, and returns function which checkes whether input string is in the list. With this tiny cute helper function, here are two examples:
let isCapital = isWord ["London"; "Paris"; "Warsaw"; "Tokyo"];;
val isCapital : (string -> bool)
let isCapitalSlow word = isWord ["London"; "Paris"; "Warsaw"; "Tokyo"] word
val isCapitalSlow : (string -> bool)
I thought these two function do excatly the same thing, but it was not the case. The book says while first one pre-computes the set from the given list, the second one will compute the set whenever the function has called.
As I learned in PL class, in order to evaluate a lambda calculus expression, every parameter should be given to the body. Lacking only one will not allow an expression to be evaulated.
Based on this, I've concluded that the first one has no parameter, so it can immidiately start evaluating when the list is given, but the second one can't start evaluating until parameter word is given. It's fine until here, but after thinking about it with the above linked question, I've become not sure whether I'm correctly understanding it or not.
Thinking from it and the answer of linked question, it seems like the evaluation continues until it becomes not able to evaluate, possibly because the lack of information, parameters, or anything. Then, is it OK to think that every situation-free part of expression will be evaluated only once and pre-computed, just like the first example?
It seems like this part may heavily affect to optimization and performance, so I want to make my understanding about this topic clear.
I've concluded that the first one has no parameter, so it can immidiately start evaluating when the list is given, but the second one can't start evaluating until parameter word is given.
This is exactly right.
It seems like the evaluation continues until it becomes not able to evaluate, possibly because the lack of information, parameters, or anything.
This is essentially also right, but it is simpler than your formulation make it sound. The "lack of information" is not something very sophisticated - it is simply the fact that lambda functions are values and cannot be evaluated until their parameters are specified.
It may be a bit easier to understand this if we rewrite everything using the fun x -> .. notation:
let isWord = fun (words : string list) =
let wordTable = Set.ofList words
fun w -> wordTable.Contains(w)
let isCapital =
isWord ["London"; "Paris"; "Warsaw"; "Tokyo"]
let isCapitalSlow = fun word ->
isWord ["London"; "Paris"; "Warsaw"; "Tokyo"] word
The evaluation proceeds from top to bottom.
The expression assigned to isWord is a function, so the body cannot be evaluated.
The expression assigned to isCapital is a function application, so it can be evaluated. This in turn evaluates the value of wordTable and returns a function - which is a function and cannot be evaluated.
The expression assigned to isCapitalSlow is a function and cannot be evaluated.
If you later call isCapitalSlow "Prague", this will be a function application and so it can be evaluated. It will then invoke isWord with a list of cities as an argument, which will, in turn, invoke Set.ofList to build wordTable and produce a function which is then evaluated with word as an argument.
Since you seem to be familiar with C#, we can rewrite this as a C# class:
class IsWord
{
HashSet<string> set;
public IsWord(string[] words) => set = new HashSet<string>(words);
public bool Contains(string word) => set.Contains(word);
}
What would the equivalent functions look like?
Func<string, bool> isCapital =
new IsWord(new[] { "London", "Paris", "Warsaw", "Tokyo" }).Contains;
Func<string, bool> isCapitalSlow =
(word) => new IsWord(new[] { "London", "Paris", "Warsaw", "Tokyo" }).Contains(word);
Note that isCapital creates an instance of the class once, and returns its contains method. So every time you call isCapital, you're actually only calling HashSet.Contains.
In isCapitalSlow you're creating an instance of IsWord, and in turn a HashSet every single time you call the method. This would naturally be slower.
In idiomatic F#, you would write this as:
let isWord words =
let wordTable = Set.ofList words
let contains word = wordTable |> Set.contains word
contains
I'm trying to learn F# at the moment and have come up on a problem I can't solve and can't find any answers for on google.
Initially I wanted a log function that would work like the printf family of functions whereby I could provide a format string and a number of arguments (statically checked) but which would add a little metadata before printing it out. With googling, I found this was possible using a function like the following:
let LogToConsole level (format:Printf.TextWriterFormat<'T>) =
let extendedFormat = (Printf.TextWriterFormat<string->string->'T> ("%s %s: " + format.Value))
let date = DateTime.UtcNow.ToString "yyyy-MM-dd HH:mm:ss.fff"
let lvl = string level
printfn extendedFormat date lvl
having the printfn function as the last line of this function allows the varargs-like magic of the printf syntax whereby the partially-applied printfn method is returned to allow the caller to finish applying arguments.
However, if I have multiple such functions with the same signature, say LogToConsole, LogToFile and others, how could I write a function that would call them all keeping this partial-application magic?
Essential I'm looking for how I could implement a function MultiLog
that would allow me to call multiple printf-like functions from a single function call Such as in the ResultIWant function below:
type LogFunction<'T> = LogLevel -> Printf.TextWriterFormat<'T> -> 'T
let MultiLog<'T> (loggers:LogFunction<'T>[]) level (format:Printf.TextWriterFormat<'T>) :'T =
loggers
|> Seq.map (fun f -> f level format)
|> ?????????
let TheResultIWant =
let MyLog = MultiLog [LogToConsole; LogToFile]
MyLog INFO "Text written to %i outputs" 2
Perhaps the essence of this question can be caught more succintly: given a list of functions of the same signature how can I partially apply them all with the same arguments?
type ThreeArg = string -> int -> bool -> unit
let funcs: ThreeArg seq = [func1; func2; func3]
let MagicFunction = ?????
// I'd like this to be valid
let partiallyApplied = MagicFunction funcs "string"
// I'd also like this to be valid
let partiallyApplied = MagicFunction funcs "string" 255
// and this (fullyApplied will be `unit`)
let fullyApplied = MagicFunction funcs "string" 255 true
To answer the specific part of the question regarding string formatting, there is a useful function Printf.kprintf which lets you do what you need in a very simple way - the first parameter of the function is a continuation that gets called with the formatted string as an argument. In this continuation, you can just take the formatted string and write it to all the loggers you want. Here is a basic example:
let Loggers = [printfn "%s"]
let LogEverywhere level format =
Printf.kprintf (fun s ->
let date = DateTime.UtcNow.ToString "yyyy-MM-dd HH:mm:ss.fff"
let lvl = string level
for logger in Loggers do logger (sprintf "%s %s %s" date lvl s)) format
LogEverywhere "BAD" "hi %d" 42
I don't think there is a nice and simple way to do what you wanted to do in the more general case - I suspect you might be able to use some reflection or static member constraints magic, but fortunately, you don't need to in this case!
There is almost nothing to add to a perfect #TomasPetricek answer as he is basically a "semi-god" in F#. Another alternative, which comes to mind, is to use a computation expression (see, for example: https://fsharpforfunandprofit.com/series/computation-expressions.html). When used properly it does look like magic :) However, I have a feeling that it is a little bit too heavy for the problem, which you described.
let memoize (sequence: seq<'a>) =
let cache = Dictionary()
seq {for i in sequence ->
match cache.TryGetValue i with
| true, v -> printf "cached"
| false,_ -> cache.Add(i ,i)
}
I will call my memoize function inside this function :
let isCached (input:seq<'a>) : seq<'a> = memoize input
If the given sequence item is cached it should print cached otherwise it will continue to add sequence value to cache.
Right now I have problems with types.
When I try to call my function like this :
let seq1 = seq { 1 .. 10 }
isCached seq1
It throws an error
"The type int does not match the type unit"
I want my function to work generic even though I return printfn. Is it possible to achieve that? And while adding value to the cache is it appropriate to give the same value to tuple?
eg:
| false,_ -> cache.Add(i ,i)
I think the problem is that your memoize function does not actually return the item from the source sequence as a next element of the returned sequence. Your version only adds items to the cache, but then it returns unit. You can fix that by writing:
let memoize (sequence: seq<'a>) =
let cache = Dictionary()
seq {for i in sequence do
match cache.TryGetValue i with
| true, v -> printf "cached"
| false,_ -> cache.Add(i ,i)
yield i }
I used explicit yield rather than -> because I think that makes the code more readable. With this change, the code runs as expected for me.
Tomas P beat me to the punch, but I'll post this up anyway just in case it helps.
I'm not too sure what you are trying to achieve here, but I'll say a few things that I think might help.
Firstly, the type error. Your isCached function is defined as taking a seq of type 'a, and returning a seq of type 'a. As written in your question, right now it takes a seq of type 'a, and returns a sequence of type unit. If you try modifying the output specification to seq<'b> (or actually just omitting it altogether and letting type inference do it), you should overcome the type error. This probably still won't do what you want, since you aren't actually returning the cache from that function (you can just add cache as the final line to return it). Thus, try something like:
let memoize (sequence: seq<'a>) =
let cache = Dictionary()
for i in sequence do
match cache.TryGetValue i with
| true, v -> printf "cached"
| false,_ -> cache.Add(i ,i)
cache
let isCached (input:seq<'a>) : seq<'b> = memoize input
All this being said, if you are expecting to iterate over the same sequence a lot, it might be best just to use the library function Seq.cache.
Finally, with regards to using the value as the key in the dictionary... There's nothing stopping you from doing that, but it's really fairly pointless. If you already have a value, then you shouldn't need to look it up in the dictionary. If you are just trying to memoize the sequence, then use the index of the given element as the key. Or use the specific input as the key and the output from that input as the value.
I have the following code which I intend to create a Map with self defined types variable and location. I understand that the key type should be ordered (some comparator function). How shall I add these rules to make this work? Also, I find the code ugly here. Do I really need the ;; at the end of a type and module?
type variable = string;;
type location = int;;
module LocationMap = Map.Make(variable);;
module EnvironmentMap = Map.Make(location);;
EDIT
This is the rest of my code:
type variable = Variable of string
type location = Location of int
module LocationMap = Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap = Map.Make(struct type t = variable let compare = compare end)
(*file read function*)
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true do
lines := input_line chan :: !lines
done;
!lines
with End_of_file ->
close_in chan;
List.rev !lines
in
(*get the inputs*)
let inputs = read_file Sys.argv.(1) in
for i = 0 to List.length inputs - 1 do
Printf.printf "%s\n" (List.nth inputs i)
done;
This has a syntax error. I am not sure why.
EDIT2
I make this work with the following edit:
type variable = Variable of string
type location = Location of int
module LocationMap = Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap = Map.Make(struct type t = variable let compare = compare end)
(*file read function*)
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true do
lines := input_line chan :: !lines
done;
!lines
with End_of_file ->
close_in chan;
List.rev !lines
(*get the inputs*)
let () =
let inputs = read_file Sys.argv.(1) in
for i = 0 to List.length inputs - 1 do
Printf.printf "%s\n" (List.nth inputs i)
done;
Sorry for the long list of questions, what does let () = do here? Is it true that when I define a function with let, I do not need in?
When applying the Map.Make functor, you need to supply a struct containing your type and a compare function:
module LocationMap =
Map.Make(struct type t = variable let compare = compare end)
module EnvironmentMap =
Map.Make(struct type t = location let compare = compare end)
You never need to use ;; in compiled code. It's only required when using the toplevel, to tell it when it should evaluate what you've typed in so far.
Some people do use ;; in compiled code, but you never need to do this and I personally never do. There is always a way to get the same effect without using ;;.
Update
The let compare = compare binds the pre-existing OCaml function compare (the infamous polymorphic comparison function) to the name compare inside the struct. So, it creates a Map that uses polymorphic compare to do its comparisons. This is often what you want.
I created a file containing your definitions (without ;;) and the above code, then compiled it with ocamlc -c. There were no syntax errors. I'm positive you don't need to use ;;, as I've written many many thousands of lines of code without it.
Note that I'm not saying that if you remove ;; from syntactically correct OCaml code, the result is always syntactically correct. There are a few idioms that only work when you use ;;. I personally just avoid those idioms.
Update 2
A let at top level of a module is special, and doesn't have an in. It defines a global value of the module. OCaml treats every source file as a module (for free, as I like to say), with a name that's the same as the source file name (capitalized).
You can actually have any pattern in let pattern = expression. So let () = ... is completely normal. It just says that the expression has unit type (hence the pattern matches).