#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 # или «другое».