F # Scala применить метод

#f#

#f#

Вопрос:

Я видел, что есть метод, который можно использовать в типе Scala с именем apply . Это позволило бы вызывать экземпляр типа, как если бы это была функция или что-то подобное. Как, например, в списке Scala, можно было бы написать myList(0) для первого элемента в списке.

Есть ли что-нибудь подобное в F #?

Комментарии:

1. Я не совсем уверен, о чем вы просите. Вы можете написать myList.[0] в F #, чтобы получить тот же эффект — вы хотите, чтобы синтаксис выглядел точно так же, как функция application?

2. Также вы хотите это для встроенных типов или только для тех, где вы управляете определением?

3. Я хотел бы выглядеть точно так же, как определение Scala. И это только для типов, которые я контролирую. Я представил пример списка как тот, который я использовал, но я намерен использовать его для других типов, которые могут не включать индекс в списке, например.

4. Кажется, в F # есть какая-то магия для распознавания собственных функций. Все они наследуются от Microsoft.FSharp.Core.FSharpFunc , и вы можете определить свои собственные типы, которые делают то же самое, переопределяя абстрактный Invoke метод, но надлежащие функции могут быть применены, а пользовательские — нет.

5. Я думаю, это может быть связано с тем, что Scala стремится немного больше выделить часть ООП — для F # Мне это действительно не нравится — зачем переводить тяжелый объект в состояние функции, если вы просто можете вернуть функцию (закрытие) в первую очередь?

Ответ №1:

Приложение функции F # внутренне основано на FSharpFunc типе. Например, (int -> int) представляется как FSharpFunc<int, int> .

Однако компилятор F #, похоже, каким-то образом знает разницу между реальной функцией F # и попыткой реализовать ее вручную, по крайней мере, когда языком реализации является F #.

Тем не менее, я смог подделать функцию F #, определив ее на C#:

 public class Foo : FSharpFunc<int, int>
{
    public override int Invoke(int n)
    {
        return n   1;
    }

}
  

а затем из F#:

 > let x = Foo() :> int -> int
val x : (int -> int)

> x 3;;
val it : int = 4 
  

Я не мог использовать тот же трюк при определении Foo в F #, даже когда я определяю его в отдельном модуле компиляции.

Компилятор F #, похоже, вставляет атрибут CompilationMapping(SourceConstructFlags.ObjectType) в свои собственные объекты, и я не могу найти способ отключить его, но мой C # работает, даже если я включил этот атрибут вручную.

Комментарии:

1. Неплохо. Я думаю, я должен проверить MSIL, чтобы увидеть, что это за результат для сравнения различий.

2. Я сделал это и ничего не смог обнаружить, но, возможно, я что-то упустил. Вполне возможно, что компилятор F # ищет свойства сборки в целом, чтобы решить, следует ли рассматривать ее как F # или «другое».