I am trying to define a valuetype that tracks changes in its constituents
(by the constituents informing values that use it, and use of some custom assignment operators) and then based on a modus(defined with the custon operator) updates differently.
I am relatively new to f# and have two problems:
1) use1: if the value is changed same=false and so I want to return the reference to the function and change same to true, however I seem to use the wrong syntax for match.
2)I can not shake the feeling my type is more complicated than it has to be.
I am trying to define a valuetype that tracks changes in its constituents
(by the constituents informing values that use it, and use of some custom assignment operators)
and then based on a modus(defined with the custon operator) updates differently.
type valtype(x) as this =
let reference= ref x
let mutable value = x
member val same= true with get, set
member val uses=[] with get, set
member this.chang1= value<- !reference
member this.chang2= this.same<- false
member val changed= this.chang1
member this.use1= fun a->a
member val used=this.use1
//here the error appears
member this.use2= if this.same then this.same<-true value<- !reference else fun a->a
// match this.same with
// |false-> this.same<-true value<- !reference
// |true-> fun a->a
member this.Value
with get()= this.used value
and set(c)=value<-c
wanted behaviour:
pseudocode:
func(x)=x+3
var1 §=func(x), var2 $=func(x), var3 &= func(x)
func(x)=x
var1(intern x), var2(intern x+2), var3(intern x+2)
Ausgabe func(1):
var1-> 1 ,var2(change:intern x)-> 1, var3-> 4
var3.orderChange var3(change:intern x)
Ausgabe func(1):
var3->1
While I can't answer your main question since I don't understand what you're trying to do, I can tell you that you have a syntax error in your use2 method. This is what you wrote:
member this.use2= if this.same then this.same<-true value<- !reference else fun a->a
And this the correct way to write that:
member this.use2=
if this.same then
this.same<-true
value<- !reference
else fun a->a
Notice how each assignment expression is on its own line. Jamming two assignment expressions onto a single line is a syntax error: the F# compiler would read this.same<-true value<- !reference as "Call the function true with the parameter value, then assign that result to this.same" — and then the second <- operator would produce a syntax error since you can't assign two values to one variable in a single line.
Also, given how you wrote that match expression below, I feel sure that what you wanted to write in your use2 method was if not this.same then ....
Can't help you with the rest of your question, but fixing the syntax of use2 will at least get you partway towards a solution.
Well I did a lot wrong, here the current hopefully correct version of this project.
type Valtype(n:unit ->'T)=
let mutable reference= n
let mutable value = n()
let uses= ResizeArray<Valtype>[]
let get1()=
value
//let get2()=
// value<-reference()
// value
let mutable get0=fun()->get1()
let get3()=
value<-reference()
get0<-fun()->get1()
value
let set1(r:unit ->'T)=
reference<-r
for u in uses do
u.Changed
value<-r()
//let set2(r)=
// reference<-fun()->r
let mutable set0=fun(r)->set1(r)
let mutable modi =0;
member x.Modi
with get()= modi
and set(i)= modi<-i%3
member x.Subscribe(f)=
uses.Add(f)
member x.Unsubscribe(f)=
uses.Remove(f)
member x.Value
with get()=get0()
member x.Set(r:unit ->'T)=set0(r:unit ->'T)
member x.Changed=
match modi with
|0-> get0<-fun()->get3()`enter code here`
|1-> value<-reference()
|_-> ()
member x.Force=
value<-reference()
Related
I'm trying to learn the TypeShape lib and playing with the IShapeMember per the snippet in the readme
type IShapeMember<'DeclaringType, 'Field> =
abstract Get : 'DeclaringType -> 'Field
abstract Set : 'DeclaringType -> 'Field -> 'DeclaringType
Here is my code in an effort to generalise a 'setter' function
let setMemberValue (value: 'b) (target: 'c) (shp: IShapeMember<'c>) =
shp.Accept { new IMemberVisitor<'c,'c> with
member x.Visit (m: ShapeMember<'c,'b>) = m.Set target value}
But this gives me the compile error: This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope.
(btw, that's not a type on the error, it indeed complains about variable 'a....)
I have tried all manner of Type wrangling but cannot get my head around what I'm doing wrong.
I'm not a TypeShape expert, but I think the problem here is that you're not honoring the signature of the Visit function, which is:
type IMemberVisitor<'TRecord, 'R> =
abstract Visit<'Field> : ShapeMember<'TRecord, 'Field> -> 'R
Note that the 'Field type parameter is determined by whoever calls Visit, not by you. Thus, your attempt to use the external value in the call to Set isn't sufficiently generic. Instead, you need a way to obtain an instance of 'Field from within the Visit function, so it works with whatever 'Field type the caller desires. This is easier said than done, but if you want a trivial example to start with, this will compile at least:
let visitor target =
{
new IMemberVisitor<'TRecord, 'R> with
member x.Visit (m: ShapeMember<'TRecord,'Field>) =
let value = Unchecked.defaultof<'Field>
let target' = m.Set target value
Unchecked.defaultof<'R>
}
There's also an example of calling Set from within Visit here, but it is more complex. I don’t think there is any way of doing it that is both simple and useful.
let setMemberValue (value: 'b) (target: 'c) (shp: IShapeMember<'c>) =
shp.Accept { new IMemberVisitor<'c,'c> with
member x.Visit (m: ShapeMember<'c,'d>) =
if typeof<'b> = typeof<'a> then //or convert 'b -> 'd function
m.Set target (box value :?> 'd)
else
failwith "The supplied type does not match the type of the target field"
}
Boxing and casting the supplied value to the type 'd did the trick. All wrapped in some form of type check in case the caller supplied value does not match that of the field being set
Let's consider this code:
type TransactionTypes =
| TransactionType1
| TransactionType2
type Test() =
let mutable lastTransactionType1 = DateTime.MinValue
let mutable lastTransactionType2 = DateTime.MinValue
let getLastTransaction transaction =
match transaction with
| TransactionType1 -> lastTransactionType1
| TransactionType2 -> lastTransactionType2
let updateLastTransaction transaction =
match transaction with
| TransactionType1 -> lastTransactionType1 <- DateTime.UtcNow
| TransactionType2 -> lastTransactionType2 <- DateTime.UtcNow
Now (with the understanding that I'm still learning F#), I would like to clarify a couple things:
Something like:
let a = DateTime.Now
does a permanent binding, so 'a' will always be the same time on subsequent uses.
But, my understanding is that if there is a parameter, like:
let a anyParameter = DateTime.Now
will be re-evaluated every time due to the presence of the parameter. Is that correct?
In the code above, the two let statements (getLastTransaction and updateLastTransaction) are private to the type (Test)
I could also have implemented them as:
member private this.getLastTransaction = ...
member private this.updateLastTransaction = ...
Is there any reason, for private functions to prefer let vs. member private this?
"let mutable" already implies the this. so the fields are accessible by both forms.
So, what is the advantage of one form vs. the other?
When you are working with members, F# inherits a lot of things from the .NET object model. A .NET object can have a couple of different things:
Fields - those are storing a value (just like fields of a record). They can be mutable or immutable.
Methods - those can be invoked with zero or more arguments (like functions)
Properties - those have no arguments (like fields); they can be read or written, but when this happens, some code is invoked. A property is basically a pair of getter and setter methods.
In F#, some of this is less visible. However, let corresponds to a field and member with arguments corresponds to a method. Your tricky case is a member without arguments. For example:
type A() =
member x.Foo = printfn "Hi"; 42
Will Hi be printed only once, or will it be printed each time you access Foo? To answer, it's useful to know that Foo is a property with a getter. The above is actually a syntactic sugar for the full version:
type A() =
member x.Foo
with get() = printfn "Hi"; 42
Now you can see that there is a method behind the Foo property! Each time you access Foo, the compiler will generate a call to the get() method, so Hi will be printed repeatedly.
In addition to Tomas' answer:
let mutable lastTransactionType1 = DateTime.MinValue
is equivalent in C# to:
internal DateTime lastTransactionType1 = DateTime.MinValue;
and
member private this.getLastTransaction ...
is the same IL as far as IL is concerned with
let getLastTransaction ...
In equivalent C#, both are
internal DateTime getLastTransactionMember(TransactionTypes transaction)
{
if (transaction.Tag != 1)
{
return lastTransactionType1;
}
return lastTransactionType2;
}
But for using F# in an idiomatic way, you would want to go with let.
There's also a difference in that member does let you use the methods in bindings before their declaration, which might be useful in some cases (read: hacks)
let getType1 = this.getLastTransactionMember TransactionType1 //this compiles
member private this.getLastTransactionMember transaction =
match transaction with
| TransactionType1 -> lastTransactionType1
| TransactionType2 -> lastTransactionType2
Consider the following F#:-
type TestClass() =
let getValFromMap m k = Map.find k m
let addToMap map k i = map |> Map.add k i
let mutable someMap : Map<string,int> = Map.empty
let getValFromMapPartial key = getValFromMap someMap key
let getValFromMapPartialAndTacit = getValFromMap someMap
member this.AddThenGet() =
someMap <- addToMap someMap "A" 10
let value = getValFromMapPartial "A"
printfn "Value from partial = %i" value // prints out
let value = getValFromMapPartialAndTacit "A" // throws
printfn "Value from partial and tacit = %i" value
[<EntryPoint>]
let main argv =
let test = TestClass()
test.AddThenGet()
0
Functions getValFromMapPartial and getValFromMapPartialAndTacit are, to my mind, identical. F# says they have the exact same type: (string -> int). And yet they behave very differently, and they are compiled very differently. Decompiling using dotPeek, I see that getValFromMapPartial is a method, whereas getValFromMapPartialAndTacit is a field that is initialized in the ctor.
F# does not complain about getValFromMapPartialAndTacit, even on the highest warning level (both in VS 2012 and 2013). And yet calling this function in my sample above fails, presumably because it has wrapped the initial, empty version of the someMap, despite its mutability.
Why is there a difference between these two functions? Should there be a warning from F# that the tacit / point-free version might fail?
The F# compiler distinguishes between let-bindings of functions, which have parameters, and values, which do not have parameters.
Value definition: A binding like let a = ... is a value definition. Its body is evaluated eagerly, "where it is", before the evaluation of anything further down the code.
Function definition: A binding like let f x = ... is a syntactic function definition, the contents of which are evaluated when the function is called.
Since someMap refers to a mutable variable, using this variable inside a function definition means reading from the variable when the function is called. However, the usage in getValFromMapPartialAndTacit reads the value at the moment of declaration.
This behavior does not stop a value from being a function. You could just as well write let f = fun x -> ... to declare a function, and ... would again be part of a function definition. However, if you were to add definitions in between the = and fun, they would be evaluated at the point of the definition of f, not when it is called.
In the question's comments, the same problem occurs with someMap being a mutable reference cell. This is the same problem. The function, as rewritten by Andrew for a mutable reference cell:
let getValFromMapPartialAndTacit = getValFromMap !someMap
Here, the dereference operator (!) is applied when the value is bound, not when the function is called. it is equivalent to:
let mapRightNow = !someMap
let getValFromMapPartialAndTacit = getValFromMap mapRightNow
getValFromMapPartial is a true syntactic function. Its signature is val getValFromMapPartial : key:string -> int. Whenever it is called, it uses the current value of someMap. That's why it works in your example; it accesses the version of someMap who has an entry.
On the other hand, getValFromMapPartialAndTacit is a lambda-computing function. Its signature is val getValFromMapPartialAndTacit : (string -> int) (notice the parentheses). The lambda has a compiler-generated closure, which contains the version of someMap at the time the lambda was computed. That's why it does not work in your example; it always acesses the same, original version of someMap who has no entry.
I get the value restriction error on let makeElem in the following code:
let elemCreator (doc: XmlDocument) =
fun name (value: obj) ->
let elem = doc.CreateElement(name)
match value with
| :? seq<#XmlNode> as childs ->
childs |> Seq.iter (fun c -> elem.AppendChild(c) |> ignore)
elem
| _ -> elem.Value <- value.ToString(); elem
let doc = new XmlDocument()
let makeElem = elemCreator doc
Why I get the value restriction error if anonymous function returned from elemCreator hasn't any generic parameters?
The compiler states that the infered type of makeElem is (string -> 'a -> XmlNode). But why it infers second parameter as 'a if I've declared it as obj?
I believe that this may be the "expected" behavior (although unfortunate in this case), as a result of the compiler's generalization and condensation processes. Consider Tomas's example:
let foo (s:string) (a:obj) = a
If you were to define
let bar a = foo "test" a
then the compiler will infer the type bar : 'a -> obj because it generalizes the type of the first argument. In your case, you have the equivalent of
let bar = foo "test"
so bar is a value rather than a syntactic function. The compiler does essentially the same inference procedure, except now the value restriction applies. This is unfortunate in your case, since it means that you have to explicitly annotate makeElem with a type annotation (or make it a syntactic function).
This looks like an unexpected behavior to me. It can be demonstrated using a simpler function:
let foo (s:string) (a:obj) = a
let bar = foo "bar" // Value restriction
One possible explanation might be that the F# compiler allows you to call a function taking parameter of some type with an argument of any subtype. So, you can call foo "hi" (new A()) without explicitly casting A to obj (which used to be required some time ago).
This implicit casting could mean that the compiler actually interprets bar as something like this:
let bar a = foo "bar" (a :> obj)
...and so it thinks that the argument is generic. Anyway, this is just a speculation, so you could try sending this as a bug report to fsbugs at microsoft dot com.
(The following is based solely on observation.)
If you have a function obj -> 'a, calls to that function are not used to infer/solve the type of its argument. An illustration:
let writeLine (arg: obj) = System.Console.WriteLine(arg)
writeLine is obj -> unit
let square x =
writeLine x
x * x
In the above function x is inferred as int because of (*). If a type could be constrained by obj then this function would not work (x would be inferred as obj prior to the use of (*), which would cause an error along the lines of: type obj does not support operator (*)).
I think this behavior is a Good Thing. There's no need to restrict a type as obj because every type is already implicitly convertible to obj. This allows your program to be more generic and provides better interoperability with the .NET BCL.
In short, obj has no bearing on type inference (yay!).
Suppose I have type A with indexer implemented, e.g. type A is a library. Now I want to extend the indexer of it, e.g. here I want to add float number into the indexer.
I worked out the following code:
type A(a:int array) =
member this.Item
with get(x) = a.[x]
and set(x) value = a.[x] <- value
type A with
member m.Item with
get(x:float) = m.[x |> int]
and set(x:float) v = m.[x |> int] <- v
But it seems not working:
let a = A([| 1;2;3 |])
a.[1]
a.[1] <- 10
a.[1.0]
For the last line, I get:
Script1.fsx(243,4): error FS0001: This expression was expected to have type
int
but here has type
float
Is extending indexer possible in F#? Thanks!
This behaves differently when the type extension is defined in a separate assembly (or separate module) and when it is in the same module as the type definition.
When both are in the same module, F# compiles them into a single class and Item becomes a standard overloaded indexer - In this case, your code works as expected (and this is how you actually wrote it here).
When they are in separate modules, F# compiles the indexer as an extension member. In this case, I get the error message you described.
Adding new overloads using extension members (e.g. new method) is possible. As far I can see, the specificaton doesn't say that this shouldn't work for indexers, so I think it is a bug (can you report it to fsbugs at microsoft dot com?)
I just tried this in FSI and it seems to work.
What compiler are you using?
This is what I fed to FSI:
type A(a:int array) =
member this.Item
with get(x) = a.[x]
and set(x) value = a.[x] <- value
type A with
member m.Item
with get(x:float) = m.[x |> int]
and set(x:float) v = m.[x |> int] <- v
let a = A([| 1;2;3 |])
a.[1] <- 10
printfn "%A" a.[1.2]
This prints '10'