Skip to content

Instantly share code, notes, and snippets.

@SchlenkR
Last active May 6, 2025 17:01
Show Gist options
  • Save SchlenkR/e99c6072a0d72f703487efb9cc96873e to your computer and use it in GitHub Desktop.
Save SchlenkR/e99c6072a0d72f703487efb9cc96873e to your computer and use it in GitHub Desktop.
Why unit - why not generalized
type UseStateBuilder() =
member _.Yield(x) = x
member _.Zero() = ()
member _.Combine(_, b) = b
member _.Delay(f) = f
member inline _.Run(f) = f ()
let useState = UseStateBuilder()
// unit -> unit
let inferedUnit (getValue: unit -> _) =
let currentValue = getValue ()
let last = useState { currentValue }
()
inferedUnit (fun () -> 1.0) // <- ERR: expected unit, not float
// unit -> unit
let autoGen (getValue: unit -> _) =
let currentValue = getValue ()
let last = useState { yield currentValue }
()
autoGen (fun () -> 1.0) // <- OK
// unit -> 'a
let manGen (getValue: unit -> 'a) =
let currentValue = getValue ()
let last = useState { currentValue }
()
manGen (fun () -> 1.0) // <- OK
type ZeroMarker = ZeroMarker
type UseStateBuilder() =
member _.Yield(x) = x
member _.Zero() = ZeroMarker
member _.Combine(_, b) = b
member _.Delay(f) = f
member _.Run(f) = f ()
let useState = UseStateBuilder()
// Expected: Yield is used implicitly
// Actual: Zero is used
let a (getValue: unit -> _) =
let currentValue = getValue ()
let last : ZeroMarker = useState { currentValue }
()
a (fun () -> 1.0)
// Expected: Yield is used implicitly
// Actual: Yield is used implicitly
let b (getValue: unit -> _) =
let currentValue = getValue ()
let last : int = useState { 2 }
()
b (fun () -> 1.0)
// WORKS (explicit yield would work)
// Meaning: Would basically work when we remove the
// YieldMarker in the builder and again use:
// member _.Yield(x) = x
let c (getValue: unit -> _) =
let currentValue = getValue ()
let last : float = useState { yield currentValue }
()
c (fun () -> 1.0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment