diff --git a/docs/release-notes/.FSharp.Core/9.0.100.md b/docs/release-notes/.FSharp.Core/9.0.100.md index eb8a8e5b052..9438303a7ed 100644 --- a/docs/release-notes/.FSharp.Core/9.0.100.md +++ b/docs/release-notes/.FSharp.Core/9.0.100.md @@ -3,6 +3,7 @@ ### Added * Enable C# collection expression support for F# lists & sets. ([Language suggestion #1355](https://github.com/fsharp/fslang-suggestions/issues/1355), [RFC FS-1145 (PR#776)](https://github.com/fsharp/fslang-design/pull/776), [PR #17359](https://github.com/dotnet/fsharp/pull/17359)) +* Add module functions for converting between `'T option` and `'T voption`. ([PR #17436](https://github.com/dotnet/fsharp/pull/17436)) ### Changed * Change compiler default setting realsig+ when building assemblies ([Issue #17384](https://github.com/dotnet/fsharp/issues/17384), [PR #17378](https://github.com/dotnet/fsharp/pull/17385)) diff --git a/docs/release-notes/.VisualStudio/17.12.md b/docs/release-notes/.VisualStudio/17.12.md new file mode 100644 index 00000000000..c247da5870b --- /dev/null +++ b/docs/release-notes/.VisualStudio/17.12.md @@ -0,0 +1,7 @@ +### Fixed + +### Added + +### Changed + +### Breaking Changes diff --git a/src/FSharp.Core/option.fs b/src/FSharp.Core/option.fs index 9c441bcad01..ba8256580ec 100644 --- a/src/FSharp.Core/option.fs +++ b/src/FSharp.Core/option.fs @@ -178,6 +178,18 @@ module Option = | Some x -> x #endif + [] + let inline ofValueOption (voption: 'T voption) = + match voption with + | ValueNone -> None + | ValueSome x -> Some x + + [] + let inline toValueOption (option: 'T option) = + match option with + | None -> ValueNone + | Some x -> ValueSome x + module ValueOption = [] @@ -355,3 +367,15 @@ module ValueOption = | ValueNone -> null | ValueSome x -> x #endif + + [] + let inline ofOption (option: 'T option) = + match option with + | None -> ValueNone + | Some x -> ValueSome x + + [] + let inline toOption (voption: 'T voption) = + match voption with + | ValueNone -> None + | ValueSome x -> Some x diff --git a/src/FSharp.Core/option.fsi b/src/FSharp.Core/option.fsi index 6b9f00be200..57adb485cb4 100644 --- a/src/FSharp.Core/option.fsi +++ b/src/FSharp.Core/option.fsi @@ -468,6 +468,36 @@ module Option = val inline toObj: value: 'T option -> 'T | null when 'T : not struct (* and 'T : not null *) #endif + /// Convert a value option to an option. + /// + /// The input value option. + /// + /// The resulting option. + /// + /// + /// + /// ValueSome 42 |> Option.ofValueOption // evaluates to Some 42 + /// (ValueNone: int voption) |> Option.ofValueOption // evaluates to None + /// + /// + [] + val inline ofValueOption: voption: 'T voption -> 'T option + + /// Convert an option to a value option. + /// + /// The input option. + /// + /// The resulting value option. + /// + /// + /// + /// Some 42 |> Option.toValueOption // evaluates to ValueSome 42 + /// (None: int option) |> Option.toValueOption // evaluates to ValueNone + /// + /// + [] + val inline toValueOption: option: 'T option -> 'T voption + /// Contains operations for working with value options. /// /// Options @@ -926,3 +956,33 @@ module ValueOption = // TODO NULLNESS: assess this change - is it a breaking change? val inline toObj: value: 'T voption -> 'T | null when 'T : not struct (* and 'T : not null *) #endif + + /// Convert an option to a value option. + /// + /// The input option. + /// + /// The resulting value option. + /// + /// + /// + /// Some 42 |> ValueOption.ofOption // evaluates to ValueSome 42 + /// (None: int option) |> ValueOption.ofOption // evaluates to ValueNone + /// + /// + [] + val inline ofOption: option: 'T option -> 'T voption + + /// Convert a value option to an option. + /// + /// The input value option. + /// + /// The resulting option. + /// + /// + /// + /// ValueSome 42 |> ValueOption.toOption // evaluates to Some 42 + /// (ValueNone: int voption) |> ValueOption.toOption // evaluates to None + /// + /// + [] + val inline toOption: voption: 'T voption -> 'T option diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl index 3da2e0a5a4d..cac2ceae8ed 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl @@ -2016,8 +2016,10 @@ Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] Filt Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] Flatten[T](Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[T]]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OfNullable[T](System.Nullable`1[T]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OfObj[T](T) +Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OfValueOption[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OrElseWith[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.FSharpOption`1[T]], Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OrElse[T](Microsoft.FSharp.Core.FSharpOption`1[T], Microsoft.FSharp.Core.FSharpOption`1[T]) +Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpValueOption`1[T] ToValueOption[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: System.Nullable`1[T] ToNullable[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: T DefaultValue[T](T, Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: T DefaultWith[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpOption`1[T]) @@ -2124,6 +2126,7 @@ Microsoft.FSharp.Core.ValueOption: Boolean IsNone[T](Microsoft.FSharp.Core.FShar Microsoft.FSharp.Core.ValueOption: Boolean IsSome[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Int32 Count[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) +Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpOption`1[T] ToOption[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[TResult] Bind[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpValueOption`1[TResult]], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[TResult] Map2[T1,T2,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]], Microsoft.FSharp.Core.FSharpValueOption`1[T1], Microsoft.FSharp.Core.FSharpValueOption`1[T2]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[TResult] Map3[T1,T2,T3,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[T3,TResult]]], Microsoft.FSharp.Core.FSharpValueOption`1[T1], Microsoft.FSharp.Core.FSharpValueOption`1[T2], Microsoft.FSharp.Core.FSharpValueOption`1[T3]) @@ -2132,6 +2135,7 @@ Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] Flatten[T](Microsoft.FSharp.Core.FSharpValueOption`1[Microsoft.FSharp.Core.FSharpValueOption`1[T]]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OfNullable[T](System.Nullable`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OfObj[T](T) +Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OfOption[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OrElseWith[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.FSharpValueOption`1[T]], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OrElse[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: System.Nullable`1[T] ToNullable[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl index aafb3256de6..b17d1201a5a 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl @@ -2019,8 +2019,10 @@ Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] Filt Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] Flatten[T](Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Core.FSharpOption`1[T]]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OfNullable[T](System.Nullable`1[T]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OfObj[T](T) +Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OfValueOption[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OrElseWith[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.FSharpOption`1[T]], Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpOption`1[T] OrElse[T](Microsoft.FSharp.Core.FSharpOption`1[T], Microsoft.FSharp.Core.FSharpOption`1[T]) +Microsoft.FSharp.Core.OptionModule: Microsoft.FSharp.Core.FSharpValueOption`1[T] ToValueOption[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: System.Nullable`1[T] ToNullable[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: T DefaultValue[T](T, Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: T DefaultWith[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpOption`1[T]) @@ -2127,6 +2129,7 @@ Microsoft.FSharp.Core.ValueOption: Boolean IsNone[T](Microsoft.FSharp.Core.FShar Microsoft.FSharp.Core.ValueOption: Boolean IsSome[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Int32 Count[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Collections.FSharpList`1[T] ToList[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) +Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpOption`1[T] ToOption[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[TResult] Bind[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpValueOption`1[TResult]], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[TResult] Map2[T1,T2,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]], Microsoft.FSharp.Core.FSharpValueOption`1[T1], Microsoft.FSharp.Core.FSharpValueOption`1[T2]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[TResult] Map3[T1,T2,T3,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[T3,TResult]]], Microsoft.FSharp.Core.FSharpValueOption`1[T1], Microsoft.FSharp.Core.FSharpValueOption`1[T2], Microsoft.FSharp.Core.FSharpValueOption`1[T3]) @@ -2135,6 +2138,7 @@ Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] Flatten[T](Microsoft.FSharp.Core.FSharpValueOption`1[Microsoft.FSharp.Core.FSharpValueOption`1[T]]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OfNullable[T](System.Nullable`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OfObj[T](T) +Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OfOption[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OrElseWith[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.FSharpValueOption`1[T]], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Microsoft.FSharp.Core.FSharpValueOption`1[T] OrElse[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: System.Nullable`1[T] ToNullable[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs index 9a566f5361d..106a1f5d7af 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Core/OptionModule.fs @@ -142,6 +142,13 @@ type OptionModule() = Assert.True( Option.ofObj null = None) Assert.True( Option.ofObj null = None) + [] + member this.OfToValueOption() = + Assert.Equal(ValueSome 3, Option.toValueOption (Some 3)) + Assert.Equal(ValueNone, Option.toValueOption (None: int option)) + Assert.Equal(Some 3, Option.ofValueOption (ValueSome 3)) + Assert.Equal(None, Option.ofValueOption (ValueNone: int voption)) + [] member this.DefaultValue() = Assert.AreEqual( Option.defaultValue 3 None, 3) @@ -380,6 +387,13 @@ type ValueOptionTests() = Assert.True(ValueOption.ofObj null = ValueNone) Assert.True(ValueOption.ofObj null = ValueNone) + [] + member this.OfToOption() = + Assert.Equal(Some 3, ValueOption.toOption (ValueSome 3)) + Assert.Equal(None, ValueOption.toOption (ValueNone: int voption)) + Assert.Equal(ValueSome 3, ValueOption.ofOption (Some 3)) + Assert.Equal(ValueNone, ValueOption.ofOption (None: int option)) + [] member this.DefaultValue() = Assert.AreEqual(ValueOption.defaultValue 3 ValueNone, 3)