using LanguageExt;
using static LanguageExt.Prelude;
///////////////////////////////////////////////////////////////////////////////////
// Option<T> doesn't allow null use at all, and it's a struct, so any references
// also can't be null.
string noValue = null;
Option<string> str1 = noValue; // Implicitly coerced to None
Option<string> str2 = Optional(noValue); // Explicitly coerced to None
Option<string> str3 = None; // None
Option<string> str4 = Some(noValue); // ValueIsNullException is thrown
Option<string> str5 = Some("Hello"); // Some of "Hello"
Option<string> str6 = Optional("Hello"); // Some of "Hello"
///////////////////////////////////////////////////////////////////////////////////
// Matching return values are also checked for null
var str = Some("Hello, World");
var res = match(str,
Some: x => noValue,
None: () => noValue); // ResultIsNullException is thrown
///////////////////////////////////////////////////////////////////////////////////
// For the rare occasions where you want an optional value that can represent
// null, there is OptionUnsafe<T>.
OptionUnsafe<string> unsstr1 = None; // None
OptionUnsafe<string> unsstr2 = SomeUnsafe(noValue); // Some(null)
///////////////////////////////////////////////////////////////////////////////////
// LanguageExt Option<T> doesn't allow access to a Value property, the only way of
// getting at the value is via Match, Map, Bind, Iter, Fold, Sum, Filter, Exists,
// ForAll, ... all of which take the state of the discriminated union into account.
///////////////////////////////////////////////////////////////////////////////////
// FSharpOption<T> allows access to the underlying .Value property, which makes it
// fundamentally unsafe, and pretty much pointless (for use in C#). You may as well
// use a reference for all the safety it gives you.
var someValue = FSharpOption<string>.Some("Hello");
var noneValue = FSharpOption<string>.None; // noneValue == null
Console.WriteLine(someValue.Value);
Console.WriteLine(noneValue.Value); // This will throw a NullReferenceException
///////////////////////////////////////////////////////////////////////////////////
// language-ext provides conversion functions for F# types to make
// interop simple:
var someValue = FSharpOption<string>.Some("Hello");
// Convert from FSharpOption<T> to Option<T>
Option<string> opt = fs(someValue);
// Convert back to FSharpOption<T> from Option<T>
FSharpOption<string> fsopt = fs(opt);