I know in F# we should bind every single value to a name.
And I think mine is ok???
But in the if statement I have the following error.
Block following this 'let' is unfinished. Expect an expression
and it comes from let min= List.nth list i.
As far as I know I bounded the min to List.nth list i. So why it should be an error?
let mutable list =[-1;2;3;4]
let mutable min=list.[0]
let mutable i=1
if min<=0 then let min= List.nth list i
If you want to mutate a mutable variable, you can use the <- operator:
if min <= 0 then min <- List.nth list i
But this is not a very functional approach. A better method is to define a new value:
let minUpdated = if min <= 0 then List.nth list i else min
Related
No problem here:
module Seq =
let private rnd = Random Environment.TickCount
let random =
fun (items : 'T seq) ->
let count = Seq.length items
items |> Seq.nth (rnd.Next count)
The signature of Seq.random is items:seq<'T> -> 'T. All good.
Yes, I know that I could just let random items = [...], that is not the point.
The point is that items is suddenly constrained to be type seq<obj> when I do this:
module Seq =
let random =
let rnd = Random Environment.TickCount
fun (items : 'T seq) ->
let count = Seq.length items
items |> Seq.nth (rnd.Next count)
... i.e. I add the Random object as a closure. If I hover over random, Intellisense shows me that the signature has become items:seq<obj> -> obj.
Interestingly, if I select the code and hit [Alt]+[Enter] to execute it in F# Interactive, the signature shows as seq<'a> -> 'a. WTH??
So, what's going on, here? Why the confusion and inconsistency in type inference?
This is due to the so-called Value Restriction. Cutting a long story short, syntactical values cannot be generic, because it might break things when mutations occur, and the compiler cannot always reliably prove immutability. (note that, even though random is a function semantically, it is still a value syntactically, and that's what matters)
But sometimes the compiler can prove immutability. This is why your first example works: when the right side of a let is a straight up lambda expression, the compiler can tell with certainty that it is immutable, and so it lets this pass.
Another example would be let x = [] - here the compiler can see that the nil list [] is immutable. On the other hand, let x = List.append [] [] won't work, because the compiler can't prove immutability in that case.
This "relaxation" of value restriction is done in F# on a case-by-case basis. F# compiler only goes as far as to handle a few special cases: literals, lambda expressions, etc., but it doesn't have a full-fledged mechanism for proving immutability in general. This is why, once you step outside of those special cases, you're not allowed to have generic values.
You can technically defeat this by adding explicit type arguments. Logically, this tells the compiler "Yes, I know it's a generic value, and that's what I meant for it to be".
let random<'t> : seq<'t> -> 't =
let rnd = Random Environment.TickCount
fun items ->
let count = Seq.length items
items |> Seq.nth (rnd.Next count)
let x = random [1;2;3]
But this will still not do what you want, because behind the scenes, such definition will be compiled to a parameterless generic method, and every time you reference such "value", the method will be called and return you a new function - with a brand new rnd baked in for every call. In other words, the above code will be equivalent to this:
let random() =
let rnd = Random Environment.TickCount
fun items ->
let count = Seq.length items
items |> Seq.nth (rnd.Next count)
let x = random() [1;2;3]
I am just getting started with F# and am trying Problem Euler problem #3. To find primes I came up with the following code to compute all primes up to a maximum number:
let rec allPrimes foundPrimes, current, max =
// make sure the current number isn't too high
// or the current number isn't divisible by any known primes
if current >= max then
foundPrimes
else
let nextValue = current + 1
if not List.exists (fun x -> current % x = 0L) foundPrimes then
allPrimes foundPrimes nextValue max
else
allPrimes (foundPrimes :: current) nextValue max
Unfortunately, this gives the error:
Only simple variable patterns can be bound in 'let rec' constructs
Why am I getting this error?
You don't want to put the commas in the declaration - change
let rec allPrimes foundPrimes, current, max =
to
let rec allPrimes foundPrimes current max =
The correct version of your original would be
let rec allPrimes (foundPrimes, current, max) =
note the brackets around the tuple. However, this would require modifying the recursive calls to also use tuple form. In the original version the compiler thinks you are trying to do something like
let a,b,c=1,2,3
which won't work for recursive functions.
Two functions are defined:
let to2DStrArray (inObj : string[][]) =
Array2D.init inObj.Length inObj.[0].Length (fun i j -> inObj.[i].[j])
let toTypedList typeFunc (strArray : string[,]) =
if (Array2D.length1 strArray) = 0 then
[]
else
List.init (Array2D.length1 strArray) typeFunc
trying to call them from fsx as follows fails:
let testData = to2DStrArray [|[||]|]
let failingCall = testData
|> toTypedList (fun row -> (Double.Parse(testData.[row,0]),
Double.Parse(testData.[row,1])))
What is a working/better way to get this code to handle the case of empty 2-dimensional string arrays?
The problem is not in toTypeList function so you don't have to check whether strArray is empty or not. It will give an error if you check inObj.[0].Length in to2DStrArray function when the input array is empty. A safe way to create an Array2D from an array of array is using array2D operator:
let to2DStrArray (inObj : string[][]) =
array2D inObj
Of course, you have to guarantee that all inner arrays have the same length. And the other function is shortened as follows:
let toTypedList typeFunc (strArray : string[,]) =
List.init (Array2D.length1 strArray) typeFunc
Given your use case, note that [|[||]|] is not an empty string[][]; it is an array which consists of only one element which in turn is an empty string array. Therefore, it causes a problem for the anonymous function you passed to toTypedList. Since the two dimensional array has length2 <= 1 and you accesses two first indices, it results in an index of bound exception. The function could be fixed by returning option values, and you can extract values from option values to use later on:
let testData = to2DStrArray [|[||]|]
let failingCall = testData
|> toTypedList (fun row -> if Array2D.length2 testData >= 2 then Some (Double.Parse(testData.[row,0]), Double.Parse(testData.[row,1])) else None)
Realistically you will have another problem as testdata.[0].Length <> testdata.[1].Length - unless you know this from somewhere else. I suspect that the best approach
let ysize = (inobj |> Array.maxBy (fun t -> t.Length)).Length
I quickly tested this and it seems to work - although it may still fail at the point where you access the array
I have written two versions of code. The first one works as expected and print "Hi". the second one gives me error that "block following this let is unfinished"
1st version
#light
let samplefn() =
let z = 2
let z = z * 2
printfn "hi"
samplefn()
2nd version
#light
let samplefn() =
let z = 2
let z = z * 2
samplefn()
Only difference is the printfn is absent in the second version. I am using Visual Studio 2010 as my IDE. I am very new to F# but this error seems very strange to me. I guess I am missing some very important concept. Please explain.
Edit: Also if I do it outside the function I get error even with the first version of code.
#light
let z = 2
let z = z * 2
printfn "Error: Duplicate definition of value z"
let binds a value to a label but otherwise doesn't do much else. Your function contains two bindings but doesn't use them, and so you get an error.
To think of it another way, all functions in F# need a return value, which is the value of the last executed expression in your function. let doesn't have a return value so your function is invalid. To fix this you can add a return value, for example:
let samplefn() =
let z = 2
let z = z * 2
()
which defines a function that does absolutely nothing (returns unit). Perhaps a better example is this:
let samplefn() =
let z = 2
let z = z * 2
z
which will return 4 (the value of the binding for label z).
I think it is helpful to understand the non-light syntax here. Let's translate:
1st Version (let binding expressions)
let samplefn() =
let z = 2 in
let z = z * 2 in
printfn "hi";;
samplefn();;
The important thing to understand here is that all non-top-level let bindings are actually expressions of the form let <variable> = <expression1> in <expression2> where <variable> is bound to the result of <expression1> in a new scope <expression2>, and <expression2> is the return value of the entire expression. The light syntax makes you believe such let bindings are variable assignments / statements, when in fact it really is true that almost everything in F# is an expression.
Perhaps the following illustrates this more clearly:
let a = (let b = 3 in b + 2) //a is 5
2nd Version (top-level let bindings)
let z = 2;;
let z = z * 2;;
printfn "Error: Duplicate definition of value z";;
Top level let-bindings are terminated with ;;, indicating the completion of what may be thought of as a statement. The top-level is a single scope, and here we get an error for trying to bind z twice within the same scope. Whereas using the expression form of let bindings in Example 1, we bind z anew for each sub-scope in the expression chain. Note that we could do something like this at the top-level:
let z = (let z = 2 in z * 2);;
A let that is not at the top level (e.g. your indented ones) has to have a statement (actually an expression, as pst notes) called a "body" following the assignment. In the first example the body is printfn "hi", while the second example has no body. That's what the compiler is complaining about.
Note that in your function definitions the inner let expressions actually create nested scopes. That is, the let z = z * 2 actually creates a new value called z and binds to it the value of the outer z times 2, then uses it in the body of the let (which is the printfn in this case). A nested let will always have a body. It is the nesting which allows the seemingly duplicate definition.
Since an outermost let does not need a body, the compiler thinks you're trying to redefine z in the same scope, which is an error. You can use parentheses to tell the compiler how to properly interpret the last example:
let z = 2
(let z = z * 2
printfn "z = %d" z)
printfn "z = %d" z
The above will print z = 4
z = 2
I have a custom class in F# and I want to implement the [] list operator such that
let myClass = new myClassObj()
let someVal = myClass.[2]
I can't seem to find this on the web - I probably don't know the right term to search for... thanks in advance
You just need to implement an Item indexed property. E.g.
type MyClass() =
member x.Item with get(i:int) = (* some logic involving i here *)
If you start at the F# language reference, and go to members, one of the topics is indexed properties.
It is worth adding that F# also supports slicing syntax (which isn't mentioned on the indexed properites MSDN page). It means that you can index not only a single element such as m.[0] but also a slice such as m.[0..5] or an unbounded range m.[5..]. This is quite useful for various numerical data types (such as matrices).
To support this feature, the type must define GetSlice method. The following example demonstrates this using a 2D scenario:
type Foo() =
member x.GetSlice(start1, finish1, start2, finish2) =
let s1, f1 = defaultArg start1 0, defaultArg finish1 0
let s2, f2 = defaultArg start2 0, defaultArg finish2 0
sprintf "%A, %A -> %A, %A" s1 s2 f1 f2
> let f = new Foo()
f.[1.., 1..10];;
val it : string = "1, 1 -> 0, 10"
The arguments are of type int option and here we use defaultArg to specify 0 as the default value.