New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type constraint: settable #671

Closed
charlesroddie opened this Issue May 18, 2018 · 5 comments

Comments

Projects
None yet
5 participants
@charlesroddie

charlesroddie commented May 18, 2018

Add type constraint: 'T : settable

We should allow:

let set (x : 'T when  'T : settable ) (value: 'T) = x <- value

Pros

This allows for cleanly binding viewmodel variables to UIs:

// If you have a mutable type that tracks changes (e.g. a Gjallarhorn mutable),
// you can then do binding approximately like this:
let bind signal (property: 'T when  'T : settable) = signal.Subscribe (fun s -> property <- s)

// usage:
do  bind textSignal label.Text

There exists a standard approach to binding in WPF and Xamarin.Forms but it was implemented without type safety using magic strings, without making use of generics.

Cons

This is not critical for the application given. Without the type constraint you can still use the same approach, but it is a bit less clean:

// this is approximate
let bind signal = signal.Subscribe

do  bind textSignal (fun s -> label.Text <- s)

Extra information

The constraint may or not include F# mutable types. For the purposes of UI programming, it is OK to restrict it to settable properties on classes.

Estimated cost (XS, S, M, L, XL, XXL): M

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this
@abelbraaksma

This comment has been minimized.

abelbraaksma commented May 21, 2018

I assume you are aware that currently you can get this behaviour with static type parameters using get_XXX and set_XXX? It is slightly different from what you ask, as it requires SRTP instead of simple generics, but it's not impossible.

@TobyShaw

This comment has been minimized.

TobyShaw commented May 22, 2018

let f (x : 'a byref) (y : 'a) = x <- y

type X() =
  member val Y : int = 5 with get, set

let x = X()
f &(x.Y) 5

Currently this fails to compile, as settable properties cannot be passed byref in F#.

"/home/runner/main.fs(8,3): error FS0257: Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'."

I feel like fixing this would be a better way of fixing this problem.

@jindraivanek

This comment has been minimized.

jindraivanek commented May 22, 2018

Using set_XXX function it can be done like this:

let f setF (y : 'a) = setF y

type X() =
  member val Y : int = 1 with get, set

let x = X()
f (x.set_Y) 5
@charlesroddie

This comment has been minimized.

charlesroddie commented May 22, 2018

Thanks for the info on .set_. I did not know about those and using those would work.

On reflection my initial post is nonsense since whether properties can be set has nothing to do with the type of the property.

@smoothdeveloper

This comment has been minimized.

smoothdeveloper commented May 22, 2018

@TobyShaw

Currently this fails to compile, as settable properties cannot be passed byref in F#.
I feel like fixing this would be a better way of fixing this problem.

It would cloud the semantics of byref, right now in C# you can't pass a property either to a ref or in parameter; this is usable only on fields or locals and I believe this should remain true in F#.

The settable constraint is interesting because it would work both for property setters and fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment