Search code examples
c#haskellfunctional-programmingnullablefunctor

Can Nullable be used as a functor in C#?


Consider the following code in C#.

public int Foo(int a)
{
    // ...
}

// in some other method

int? x = 0;

x = Foo(x);

The last line will return a compilation error cannot convert from 'int?' to 'int' which is fair enough. However, for example in Haskell there is Maybe which is a counterpart to Nullable in C#. Since Maybe is a Functor I would be able to apply Foo to x using fmap. Does C# have a similar mechanism?


Solution

  • We can implement such functionality ourselves:

    public static class FuncUtils {
    
        public static Nullable<R> Fmap<T, R>(this Nullable<T> x, Func<T, R> f)
            where T : struct
            where R : struct {
            if(x != null) {
                return f(x.Value);
            } else {
                return null;
            }
        }
    
    }
    

    Then we can use it with:

    int? x = 0;
    x = x.Fmap(Foo);
    

    It will thus call the function Foo if x is not null. It will wrap the result back in a Nullable<R>. In case x is null, it will return a Nullable<R> with null.

    Or we can write a more equivalent function (like fmap in Haskell) where we have a function Fmap that takes as input a Func<T, R> and returns a Func<Nullable<T>, Nullable<R>> so that we can then use it for a certain x:

    public static class FuncUtils {
    
        public static Func<Nullable<T>, Nullable<R>> Fmap<T, R>(Func<T, R> f)
            where T : struct
            where R : struct {
            return delegate (Nullable<T> x) {
                if(x != null) {
                    return f(x.Value);
                } else {
                    return null;
                }
            };
        }
    
    }
    

    We can then use it like:

    var fmapf = FuncUtils.Fmap<int, int>(Foo);
    fmapf(null);  // -> null
    fmapf(12);    // -> Foo(12) as int?