Have you read
What are you actually trying to do (what needs solving, how will you use mbar)?
It may or may not be germaine to value restrictions, but it's certainly related - the docs seem a little confusing...
The page the article references ([link:msdn.microsoft.com])
states:
> let max a b = if a > b then a else b
> The type is inferred to be 'a -> 'a -> 'a.
I beleive this should be:
- The type is inferred to be 'a -> 'a -> 'a when 'a comparison
It also states:
> The max function also works with any type that supports the greater-than operator
Is this true? I thought the "comparison" constraint asserted the presence of I(Structural)Comparison, not the definition of the single ">" operator - but even reading the spec., it's not clear to me.
Also, how does the ">" operator magically enforce the comparison constraint in the generic definition of "max"? - I could define the ">" operator to reformat my hard-drive and return an XML document, right?
thanks
It may or may not be germaine to value restrictions, but it's certainly related - the docs seem a little confusing...
The page the article references ([link:msdn.microsoft.com])
states:> let max a b = if a > b then a else b
> The type is inferred to be 'a -> 'a -> 'a.I beleive this should be:
- The type is inferred to be 'a -> 'a -> 'a when 'a comparison
This documentation was presumably written before comparison constraints were introduced into the language, but it is no longer accurate - you are correct.
It also states:
> The max function also works with any type that supports the greater-than operator
Is this true? I thought the "comparison" constraint asserted the presence of I(Structural)Comparison, not the definition of the single ">" operator - but even reading the spec., it's not clear to me.
Also, how does the ">" operator magically enforce the comparison constraint in the generic definition of "max"? - I could define the ">" operator to reformat my hard-drive and return an XML document, right?
thanks
This statement from the documentation is still correct (depending on how you interpret it). Because max is defined in terms of the (>) operator it inherits the constraints of the (>) operator, and will therefore work on values of any type where the (>) operator also works.
You are right that you could always redefine the (>) operator to do whatever you want; in that case it's the constraints imposed by the definition of the (>) operator which is in scope where the max function is defined which will apply to its arguments. The value
1
Microsoft.FSharp.Core.Operators.(>)
has the comparison constraint on its argument type which is why that constraint propagates to the definintion of max. However if you did this:
1 2 3
let (>) x y = System.IO.Directory.Delete(@"C:\", true); true let max a b = if a > b then a else b
(which I don't recommend) then the type of max is just
1
'a -> 'a -> 'a
, with no constraint.
Thanks for the response.
> This documentation was presumably written before comparison constraints were introduced into the language, but it is no longer accurate - you are correct.
I figured. (This is from the VS2010 doc page tho' - I wonder what else is lurking...) I know docs are hard to maintain...
I'm still a little confused about this statement:
>This statement from the documentation is still correct (depending on how you interpret it). Because max is >defined in terms of the (>) operator it inherits the constraints of the (>) operator, and will therefore work
>on values of any type where the (>) operator also works.
Ok, I think I understand now. So there is the "builit-in" (>) operator *function* which there can be only one of because F# doesn't allow overloading of let-bound functions, only members - so there can be only one of those, and that standard one has the comparison constraint on it - and redefining this one has bad consequences. If I have a static member (>) overload on my own type, then that will be used, and it may or may not have a comparison constraint. And extension methods can't provide operator overloads, I can't redefine (>) on something like int's myself, so that sidesteps that fly in the ointment. Is that all correct?
I'm still a little confused about this statement:
>This statement from the documentation is still correct (depending on how you interpret it). Because max is >defined in terms of the (>) operator it inherits the constraints of the (>) operator, and will therefore work
>on values of any type where the (>) operator also works.Ok, I think I understand now. So there is the "builit-in" (>) operator *function* which there can be only one of because F# doesn't allow overloading of let-bound functions, only members - so there can be only one of those, and that standard one has the comparison constraint on it - and redefining this one has bad consequences. If I have a static member (>) overload on my own type, then that will be used, and it may or may not have a comparison constraint. And extension methods can't provide operator overloads, I can't redefine (>) on something like int's myself, so that sidesteps that fly in the ointment. Is that all correct?
Not quite. If you use a random symbolic operator (say (+++)), by default it requires that the type of one of its arguments has a static member with the same name ((+++) in this case). However, you can always provide your own let-bound definition of an operator which shadows that default behavior, in which case the operator can do whatever you want. For instance, if you have a let-bound definition:
1
let (+++) (x:int) (y:string) = false
then when that definition is in scope you will only be able to apply the (+++) operator to ints and strings (getting a bool result) regardless of whether there are any types which define a static (+++) member. If you wanted to, you could define your own let bound version of an operator that has the default behavior by using an inline definition (e.g.
1
let inline (+++) x y = ((^a or ^b):(static member (+++) : ^a * ^b -> ^c)(x,y))
), though there wouldn't be much of a point to doing so unless there were another definition of (+++) in scope that you wanted to shadow.
The F# libraries provides some built in operators which are automatically in scope (such as those in the Microsoft.FSharp.Core.Operators module. These include the (>), (<), etc. operators, which are explicitly defined to have type
1
'a -> 'a -> bool when 'a : comparison
. Therefore, it doesn't matter if you define a type which has a (>) static member - this won't be called by the (>) operator (unless you shadow the version from the standard library.
Hopefully that makes it clear what's going on in the examples below:
1 2 3 4 5 6 7 8 9 10 11
type T = A | B of int let test1 = A > (B 4) // compiles; (>) can be used because type T satisfies the comparison constraint let test2 = T.(>)(A, (B 4)) // doesn't compile; there is no such static member type U() = static member (>)(_:U,_:U) = true let test3 = (U()) > (U()) // doesn't compile; type U doesn't satisfy the comparison constraint let test4 = U.(>)(U(), U()) // compiles; this static member exists let inline (>) a b = ((^a or ^b):(static member (>): ^a * ^b -> ^c)(a, b)) // shadows normal (>) definition let test5 = A > (B 4) // doesn't compile; no such static member on T let test6 = (U()) > (U()) // compiles
I was trying to insert into a mutable datastructure, something like
1 2 3 4
(* incorrect code *) type 'a foo = E | T of 'a foo * 'a foo let mutable mbar = E mbar <- insert 123 mbar
Yes I have the blogpost, I also tried to get the approaches mentioned working.
I tried adding explicit type annotation (without success)
1
let mutable mbar : 'a foo = E
The article also mentioned making the type non-generic, but I would like it to be generic.
I just can't figure out how to get this to work.
Thanks.
Koen
I was trying to insert into a mutable datastructure, something like
1 2 3 4(* incorrect code *) type 'a foo = E | T of 'a foo * 'a foo let mutable mbar = E mbar <- insert 123 mbarYes I have the blogpost, I also tried to get the approaches mentioned working.
I tried adding explicit type annotation (without success)1let mutable mbar : 'a foo = EThe article also mentioned making the type non-generic, but I would like it to be generic.
I just can't figure out how to get this to work.
Thanks.
Koen
Remember that a generic value bar:'a foo
basically means that for any type 't that I give you, you can produce a value of type 't foo
. Given this fact, and assuming that insert is defined to have type
1
'a -> 'a foo -> 'a foo
, maybe you can see why your code should not be expected to work:
1
insert 123 mbar
would have type int foo
because you're inserting an int into it. However, even if mutable generic values <i>were <i>allowed, you couldn't assign a value of type <c>int foo</c> to a mutable generic variable of type <c>'a foo</c>. This is because it would no longer be possible to treat your <c>mbar</c> as a <c>'t foo</c> for all types 't (for instance, using 't = string, there would be no longer be any way to for the compiler to treat mbar as a <c>string foo</c>).
You won't be able to write code like
1
mbar <- insert 123 mbar
unless that code is contained in a generic function or class that is parameterized by the generic type 'a. For example this
1 2 3 4 5 6
type foo<'a> = E | T of foo<'a> * foo<'a> let DoStuff<'a>() = let mutable mbar : foo<'a> = E mbar <- T(mbar,mbar) DoStuff<int>() DoStuff<string>()
is ok, since each call to DoStuff knows the concrete type Does that help?
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hi All,
I'm a bit puzzled by F# value restriction. I have been reading about it on the internet but the I just cannot grasp it ... yet.
If I define my own datastructure and assign it, all is ok:
But if I would assign to a mutable variable like so:
I receive an error
Is there anyone that can help solve this issue?
Many thanks,
Koen