Reputation:
So I have this function that calculates the frequency percentage of each letter given a string. this function is called "frequency" and utilizes other helper functions that I've wrote ("count", "lowerCases", and "percent"). But when I try to return my result, I keep getting a mismatch error. Here is my code below:
let frequency(str:string) : float =
let myList = ['a'..'z']
for i=0 to 25 do
printf "%f" (percent ((count myList.[i] str) (lowerCases str)))
System.Console.WriteLine(frequency"hello world")
I keep getting this error:
This expression was expected to have type float but here has type unit
How can I fix this type mismatch error? I've already tried setting my result to a different variable and calling that variable, but that didn't work.
Upvotes: 3
Views: 435
Reputation: 5510
An F# function binds a single value of the single expression in its body (the one which comes last after all let
-bindings, simply speaking. In your case, this expression is
for i=0 to 25 do
printf "%f" (percent ((count myList.[i] str) (lowerCases str)))
It has the type unit
, meaning it does not return anything useful but a special value ()
, while the let frequency ... : float =
binding says that it returns a float
. Hence the error.
printf
already prints to console. What you want is probably
let frequency(str:string) : unit =
let myList = ['a'..'z']
for i=0 to 25 do
printf "%f" (percent ((count myList.[i] str) (lowerCases str)))
do frequency "hello world"
It is idiomatic to omit the : unit
annotation in such a function, and let the compiler infer the return type. This code does not shine the F# glory, naturally, but does the job.
As it appears you are learning the language, here's an exercise, maybe for the future. Your function lumps together computing the letter frequencies and printing them, and functional programming is all about composition. What if you want to display the result in a window instead of printing it to console, or format it differently? Try to write two functions, one returning a data structure with the letter frequencies, and another printing it.
Upvotes: 1
Reputation: 6510
You've declared the function as returning a float:
let frequency(str:string) : float =
However, your function doesn't return a float, it just prints one out:
printf "%f" (percent ((count myList.[i] str) (lowerCases str)))
The printf
function returns unit
, meaning that it effectively has no return value (it has a constant return value of the singleton type unit
).
There are two things that I see you needing to fix here. You need to return a value from the function (by having it be the value of the last line), and I think you will want your return type to be a list or a map instead of a single value (else, how would you know two which letter the frequency applies)?
You can achieve this result by just calling your percent
function from List.map
, and then making Map
of the list:
let frequency(str:string) : Map<char, float> =
['a'..'z']
|> List.map (fun letter -> letter, (percent ((count letter str) (lowerCases str))))
|> Map.ofList
Upvotes: 1