Можно ли написать интерфейс функтора для .NET? - PullRequest
2 голосов
/ 07 июля 2011

Функциональные языки часто имеют Functor типы / интерфейсы.

В .NET интерфейс Functor будет интерфейсом, реализуемым с помощью универсальных типов (T<A>), который имеет функцию с именем fmapберет функцию из типа контейнера (A) в другой тип (B) и возвращает объект с типом контейнера B.

Например, у типа List<A> будет метод List.fmap.,Подпись будет выглядеть примерно так:

public List<B> fmap<B>(Func<A,B>);

Возможно ли создать такой интерфейс?Возможно ли сделать что-то подобное?Существуют ли пакеты, которые предоставляют подобный интерфейс и предоставляют методы расширения для очевидных классов (List<T>, Dictionary<A,B>, Set<A> и т. Д.)?

Обновление :

Я знаю, что IEnumerable объекты почти делают это.Ключевым отличием является то, что IEnumerable.Select возвращает IEnumerable, а не тип разработчика.Например, List.Select (A => B) возвращает IEnumerable, а не List.Это показывает, почему вы не можете реализовать IMappable очевидным способом для .NET, но есть ли хак или дополнительная информация о типах, которую вы могли бы использовать для эффективной реализации?

Ответы [ 2 ]

2 голосов
/ 07 июля 2011

Сложность задания типа для fmap заключается в том, что он параметризован переменной типа с более высоким родом, типом контейнера. Таким образом, помимо простой полиморфной функции, например, map в списках:

map :: (a -> b) -> List a -> List b

fmap обобщает это для работы с любым контейнером, а также с любым типом элемента:

fmap :: Functor (f :: * -> *) => (a -> b) -> f a -> f b

Проблема в C # состоит в том, что f - это переменная типа с более высоким родом (это функция типа). Так как C # не поддерживает более высокие типы, вам не повезло, если вы напишете это напрямую, подумайте.

2 голосов
/ 07 июля 2011

Хорошо, основываясь на комментарии, я подозреваю ответа нет - вам понадобятся универсальные типы более высокого порядка. Вы бы хотели что-то вроде:

// Not real syntax!
interface IFunctor<TFunctor<?>, TValue>
    where TFunctor<X> : IFunctor<TFunctor<X>, TValue>
{
    TFunctor<TProjection> Project<TProjection>(Func<TValue, TProjection> func);
}

Проблема состоит в том, чтобы выразить идею о том, что реализация интерфейса должна также быть универсальной определенным образом и позволять использовать эти общие отношения в остальной части интерфейса. Боюсь, это не является частью обобщений .NET.

Джо Даффи писал о , желающем для типов более высокого порядка до сих пор - к сожалению, я не могу сказать, актуальна ли эта статья, так как я не могу добраться до нее в данный момент. (Его блог-сервер несколько временен, но контент отличный:)


Это не совсем понятно, но возможно, вы просто говорите о LINQ to Objects , в основном. Например:

var kids = people.Where(x => x.Age < 18) // Filtering
                 .Select(x => x.Name)    // Projection
                 .ToList();

Вы можете написать более универсальный интерфейс, например,

public interface IFunctor<T>
{
    IFunctor<TOther> Foo<TOther>(Func<T, TOther> selector);
}

... но на самом деле такой интерфейс не реализован List<T> и т. Д. LINQ to Objects работает вместо этого с помощью методов расширения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...