let downTo n =
if (n.Equals(0)) then
printfn "\n Empty List Provided \n";;
else
List.rev(List.init n (fun index -> index + 1));;
I'm trying to create a list 'n' length, if a number greater than 0 is passed. If not, print an error message. The List works by itself, but not in the If-Else statement. How can this be accomplished? Please help.
F# if expressions are expressions not statements. What this means is that the two parts of the expression need to have the same type. In this case, one side has a type of int list and the other side has a type of unit.
Something like this would work for you better:
let downTo n =
if (n.Equals(0)) then
printfn "\n Empty List Provided \n"
[]
else
List.rev(List.init n (fun index -> index + 1))
or, alternatively, you could throw an exception but this has the drawback that you have to do a try/catch around it.
Related
I have an exercise that asks me to make a recursive function that uses # to create a list of [1;2;3..n]. Unfortunately I cannot get this method to work.
let lstInt: int list = []
let rec oneToN (n:int) : int list =
let addList = [n]
match n with
0 ->
lstInt
|_ ->
lstInt#addList
oneToN (n-1)
I have tried making my list mutable, but that doesn't seem to actually matter nor make much sense as you can still add and remove elements from lists in f# even though it is not mutable.
I have also tried removing space between # but that shouldn't matter either.
Edit: I should clarify, the issue is the lstInt#addList, which gives me the error:
"The result of this expression has type 'int list' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr"
That warning is not the issue, but it points you to the issue: you're creating a new list which is a concatenation of an empty list and [n], but then you're doing nothing with that new list. It's just dropped on the floor.
After that, you proceed to call oneToN (n-1) recursively and return its result. At the end of recursion, the very last call to oneToN will ultimately return an empty list, and that will be the return value of every previous iteration, since every iteration (except the last one) returns whatever the next iteration returns.
What you need to do is call oneToN (n-1), which will give you a list of numbers from 1 to n-1, and then append [n] to that list. And the result of that appending would be your return value: after all, if you take a list of numbers from 1 to n-1 and attach n to the end of it, you'll get a list of numbers from 1 to n.
let rec oneToN (n:int) : int list =
let addList = [n]
match n with
0 ->
lstInt
|_ ->
(oneToN (n-1)) # addList
Imagine that I have function printList that takes list as an argument and prints all the elements in the list one by one in a new row followed by the position in the list also while having space between them.
E.G
1: 4
2: 9
3: 12
How can I implement this in F# using recursion without any built-in features ?
I assume it might look something like this, but I've problems with int, unit types.
let rec printList l = function
match l with
| [] -> 0
| head::tail -> // something
There are two advices I can give you so you can implement the printList function:
you will have to make printList a non-recursive function and define a local recursive helper function in order to keep track of the index of the value.
all branches of your match expression must return the same type and here what you want is the unit type.
In case you are still stuck, I provide the solution below.
Solution
let printList list =
let rec helper index list =
match list with
| [] -> ()
| head :: tail ->
printfn "%d: %A" index head
helper (index + 1) tail
helper 1 list
I'm trying to create a list of size n pulling elements from a larger, already created list.
I'm getting an error saying:
This value is not a function and cannot be applied.
Incomplete pattern matches on this expression. For example, the value '[]' may indicate a case not covered by the pattern(s). at 7,16
Can anyone help see what I'm doing wrong? Also, I'm trying to understand F# so I don't really want anything that can do what I'm asking for me, unless it's an FYI kind of thing. But I'd still want help creating a function to do this.
//create a list of size n from beginning of a dataset
let populateList n =
let starterList = []
let data = [1;2;3;4;5;6;7;8]
let rec helper count aList =
let head::tail = aList
if count < k then head :: helper count+1 tail else []
helper 0 data
populateList 3
It's failing to run because of this:
head :: helper count+1 tail
Because function invocations have higher operator precedence than the infix + operator, this is being interpreted as:
head :: ((helper count) + (1 tail))
Since 1 is not a function, you are getting an error here.
You can fix this by adding parentheses:
head :: helper (count+1) tail
The "Incomplete pattern matches" warning will not prevent it from running, but it does indicate something that you should address because it can lead to a runtime error.
The correct way to address it is by using pattern matching to cover all the possible patterns:
let rec helper count aList =
match aList with
| head::tail -> if count < n then head :: helper (count+1) tail else []
| [] -> []
This will ensure that you do not attempt to split an empty list into a head and a tail.
Since this function now returns [] both in the base case and in the case that aList is empty, you can further simplify this by using when and a default match condition:
let rec helper count aList =
match aList with
| head::tail when count < n -> head :: helper (count+1) tail
| _ -> []
let x = [for p in db.ParamsActXes do
if p.NumGroupPar = grp then
yield p.Num, p.Name]
Here is my sequence but the problem is it returns the list of tuples, I can't access single tuple element like
let str = "hello" + x.[1]
and that is the trouble.
how can I realize this functionary ?
To access the second element of a 2-tuple you can either use snd or pattern matching. So if tup is a 2-tuple, where the second element of tup is a string, you can either do:
let str = "hello" + snd tup
or
let (a,b) = tup
let st = "hello" + b
Note that snd only works with 2-tuples, not tuples with more than two elements.
To give you one more alternative solution, you can just create a filtered sequence containing values of the original type by writing yield p:
let x = [ for p in db.ParamsActXes do
if p.NumGroupPar = grp then
yield p ]
And then just access the property you need:
let str = "hello" + x.[1].Name
This is probably a good idea if you're returning only several properties of the p value. The only reason for yielding tuples would be to hide something from the rest of the code or to create sequence that matches some function you use later.
(Also, I would avoid indexing into lists using x.[i], because this is inefficient - but maybe this is just for ilustration in the sample you posted. Use an array if you need index based access by wrapping sequence expression into [| ... |])
Just to throw one more possibility out there, if you are running the .NET 4.0 build of F# 2.0 you can perform a runtime cast from the F# tuple to the .NET 4.0 System.Tuple and then use the ItemX properties of the .NET 4.0 tuples to access the tuple element you need,
let x = (1, 1.2, "hello")
let y = ((box x) :?> System.Tuple<int, float, string>);;
y.Item3 //returns "hello"
However, I would never use that, instead opting for the pattern match extraction. (also, I've read places that the F# compiler may not always choose to represent its tuples as .NET 4.0 tuples, so there may be a possibility that the cast would fail).
Reading your comments in some of the other answers, I'm unsure why the pattern matching solution doesn't work for you. Perhaps you want to access the tuple item at a certain place within an expression? If so, the previous would certainly work:
let str = "hello" + ((box x.[1]) :?> System.Tuple<int,string>).Item2 //though might as well use snd and fst for length 2 F# tuples
but you can achieve the same ends using the pattern matching extraction technique too (again, assuming this is even what you're after):
let str = "hello" + (let (_,name) = x.[1] in name)
you can access individual tuple from the list of tuple using List.nth.
let first, second = List.nth x 0
first and second represents the individual element of the tuple.
I'm trying to learn F# by going through some of the Euler problems and I found an issue I haven't been able to figure out. This is my naive solution.
let compute =
let mutable f = false
let mutable nr = 0
while f = false do
nr <- nr + 20
f = checkMod nr
nr
When i do this I get the error message warning FS0020: This expression should have type 'unit', but has type 'bool' on the expression "nr <- nr +20". I've tried rewriting and moving the expressions around and I always get that error on the line below the while statement.
I'm writing this using VS2010 Beta.
Since I can imagine this weg page becoming the 'canonical' place to look up information about warning FS0020, here's my quick summary of the three commonest cases in which you get the warning, and how to fix them.
Intentionally discarding the result of a function that is called only for its side-effects:
// you are calling a function for its side-effects, intend to ignore result
let Example1Orig() =
let sb = new System.Text.StringBuilder()
sb.Append("hi") // warning FS0020
sb.Append(" there") // warning FS0020
sb.ToString()
let Example1Fixed() =
let sb = new System.Text.StringBuilder()
sb.Append("hi") |> ignore
sb.Append(" there") |> ignore
sb.ToString()
Warning is useful, pointing out an error (function has no effects):
// the warning is telling you useful info
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
let l = [1;2;3]
List.map (fun x -> x * 2) l // warning FS0020
printfn "doubled list is %A" l
let Example2Fixed() =
let l = [1;2;3]
let result = List.map (fun x -> x * 2) l
printfn "doubled list is %A" result
Confusing assignment operator and equality comparison operator:
// '=' versus '<-'
let Example3Orig() =
let mutable x = 3
x = x + 1 // warning FS0020
printfn "%d" x
let Example3Fixed() =
let mutable x = 3
x <- x + 1
printfn "%d" x
The following line:
f = checkMod nr
is an equality check, not an assignment as I believe you are intending. Change it to:
f <- checkMod nr
and all should work fine. I'm not sure why you've used the correct syntax on the previous line and not that line...
Also, the line while f = false do should really be simplified to while not f do; equality checks on booleans are rather convoluted.
As I side note, I feel a need to point out that you are effectively trying to use F# as an imperative language. Use of mutable variables and while loops are strongly discouraged in functional languages (including F#), especially when a purely functional (and simpler) solution exists, as in this situation. I recommend you read up a bit on programming in the functional style. Of course, just getting to grips with the syntax is a useful thing in itself.
If you're trying to adopt the functional style, try to avoid mutable values.
For example like this:
let nr =
let rec compute nr =
if checkMod nr then nr else compute (nr + 20)
compute 0
while expressions in F# take a little getting used to if you're coming from an imperative language. Each line in a while expression must evaluate to unit (think void from C++/C#). The overall expression then also evaluates to unit.
In the example:
nr <- nr + 20
evaluates to unit whereas
f = checkMod nr
evaluates to a bool as Noldorin noted. This results in a warning message being reported. You can actually turn the warning off if you so desire. Just put the following at the top of your file:
#nowarn "0020"
I've been programming in an imperative style for a long time, so getting used to the functional programming mindset took a while.
In your example, you're trying to find the first multiple of 20 that passes your checkMod test. That's the what part. For the functional how part, I recommend browsing through the methods available to sequences. What you need is the first element of a sequence (multiples of 20) passing your test, like this:
let multi20 = Seq.initInfinite (fun i -> i*20)
let compute = multi20 |> Seq.find checkMod
The first let generates an infinite list of twentyples (I made that one up). The second let finds the first number in said list that passes your test. Your task is to make sure that there actually is a number that will pass the test, but that's of course also true for the imperative code.
If you want to condense the two above lines into one, you can also write
let computeCryptic = Seq.initInfinite ((*) 20) |> Seq.find checkMod
but I find that pulling stunts like that in code can lead to headaches when trying to read it a few weeks later.
In the same spirit as Brian's post, here is another way to get warning FS0020: In a nutshell, I accidentally tupled the function arguments.
Being an F# newbie, I had a difficult time debugging the code below, which for the second line (let gdp...) gave the warning FS0020: This expression should have type 'unit', but has type '(string -> ^a -> unit) * string * float'. It turns out that line was not the problem at all; instead, it was the printfn line that was messed up. Removing the comma separators from the argument list fixed it.
for country in wb.Regions.``Arab World``.Countries do
let gdp = country.Indicators.``GDP per capita (current US$)``.[2010]
let gdpThous = gdp / 1.0e3
printfn "%s, %s (%.2f)" country.Name, country.CapitalCity, gdpThous