Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a type extension for T[] in F#?

In C#, I can define an extension method for a generic array of type T like this:

public static T GetOrDefault<T>(this T[] arr, int n)
{
    if (arr.Length > n)
    {
        return arr[n];
    }

    return default(T);
}

but for the life of me I can't figure out how to do the same in F#! I tried type 'a array with, type array<'a> with and type 'a[] with and the compiler wasn't happy with any of them.

Can anyone tell me what's the right to do this in F#?

Sure, I can do this by overshadowing the Array module and add a function for that easily enough, but I really want to know how to do it as an extension method!

like image 267
theburningmonk Avatar asked Aug 06 '12 21:08

theburningmonk


People also ask

What is a type extension?

Type extensions (also called augmentations) are a family of features that let you add new members to a previously defined object type. The three features are: Intrinsic type extensions. Optional type extensions. Extension methods.

What keyword is used to define an extension method?

Extension Method uses the "this" keyword as the first parameter. The first parameter always specifies the type that the method operates on. The extension method is written inside a static class and the method is also defined as static.

Does Java support extension methods?

Java does not support extension methods. Instead, you can make a regular static method, or write your own class.


2 Answers

You have to write the array type using 'backtick marks' - like this:

type 'a ``[]`` with
  member x.GetOrDefault(n) = 
    if x.Length > n then x.[n]
    else Unchecked.defaultof<'a>

let arr = [|1; 2; 3|]
arr.GetOrDefault(1) //2
arr.GetOrDefault(4) //0

Edit: The syntax type ``[]``<'a> with ... seems to be allowed as well. In the F# source (prim-types-prelude.fs) you can find the following definition:

type ``[]``<'T> = (# "!0[]" #)
like image 148
Johan Kullbom Avatar answered Oct 08 '22 18:10

Johan Kullbom


Good question. I can't figure out how to extend 'T[] but you can take advantage of the fact that arrays implement IList<_> to do:

type System.Collections.Generic.IList<'T> with
  member x.GetOrDefault(n) = 
    if x.Count > n then x.[n]
    else Unchecked.defaultof<'T>

let arr = [|1; 2; 3|]
arr.GetOrDefault(1) //2
arr.GetOrDefault(4) //0
like image 34
Daniel Avatar answered Oct 08 '22 19:10

Daniel