.NET + Reflection.Emit = type classes

agaaaa

Когда надоедает завидовать Haskell'ю: http://ntypeclasses.codeplex.com/documentation

Dasar

для тех кто не знает что такое type class, в чем выигрыш от либы?

agaaaa

Если очень вкратце, то либа упрощает написание обобщённого кода, который обычными generic'ами не описать. Например, можно требовать наличия статических методов с определённой сигнатурой, можно расширять типы не поддерживающие требуемые операции. По ссылке объяснено на векторах, собственно.

agaaaa

Допилил утилиту, с помощью которой можно проверить сборку на неправильную подстановку типов в type class'ы. Достаточно добавить её в post-build event в случае successful build и передать как параметр имя выходной сборки $(TargetPath и мы получим ошибку на этапе компиляции, если не хватает каких-то методов.
Например: Field<Double>: no implementation for Double get_MinusOne
Сел пилить исходники F# с целью внедрения нативной поддержки сабжа.

kokoc88

По ссылке объяснено на векторах, собственно.
Документация по ссылке настолько непонятная, что я не могу ни обосрать, ни похвалить это поделие.
Можно объяснить на пальцах для простых смертных, что это такое и зачем это в ООП языке?
Ибо солнце погаснет раньше, чем я пойму, как переписать код на Haskell в код на C#, и зачем мне это может понадобиться:
member :: (Eq a) => a -> [a] -> Bool
member y [] = False
member y (x:xs) = (x == y) || member y xs

apl13

Я на плюсах могу :cool:
template<typename a, class InputIterator> bool member(const a &y, InputIterator xs_begin, InputIterator xs_end) {
if(xs == xs_end) return false;
return y == *xs_begin || member(y, ++xs_begin, xs_end);
}

apl13

А вместо Eq a => написать в начале функции assert (y == y). :cool:

apl13

assert (y == y && (xs_start == xs_end || *xs_start == y || !(*xs_start == y

:punk:

kokoc88

*xs_start == y || !(*xs_start == y)
Какие же усилия нужны, чтобы это было false?..

apl13

Усилия нужны такие: или InputIterator не дереференсится, или результат дереференса нельзя сравнивать с a.
В том смысле, что если скомпилировалось, значит труе, иначе ошибка компиляции, как и бывает в хаскеле при тайп мисматче.
Или ты знаешь способ как-то еще сказать, что InputIterator - это именно итератор, да еще и в контейнере, содержащем a?

apl13

Еще я изменил в прототипе a на const a&, а это уже неявно предполагает, что оператор сравнения обязательно должен быть referentially transparent, с явной декларацией константности параметров.
Но если его иначе определить, тогда придется передавать по значению, а это копирование. :crazy:

kokoc88

Усилия нужны такие: или InputIterator не дереференсится, или результат дереференса нельзя сравнивать с a.
Зачем тогда assert?
В том смысле, что если скомпилировалось, значит труе, иначе ошибка компиляции, как и бывает в хаскеле при тайп мисматче.
Ошибка компиляции будет и без assert.
Или ты знаешь способ как-то еще сказать, что InputIterator - это именно итератор, да еще и в контейнере, содержащем a?
На тип InputIterator можно наложить compile type ограничения. В boost есть библиотеки для этого.

kokoc88

Какие же усилия нужны, чтобы это было false?..
Компилируется, а потом падает в рантайме. К слову об assert-ах. ;)
 
class always_false
{
public:
operator bool
{
return false;
}

bool operator!
{
return false;
}
};

class comparable
{
public:
always_false operator==(comparable& other)
{
return always_false;
}

always_false operator!=(comparable& other)
{
return always_false;
}
};

...
comparable y;
std::cout << (y == y ? "true" : "false") << std::endl;
std::cout << (!(y == y) ? "true" : "false") << std::endl;
std::cout << (y != y ? "true" : "false") << std::endl;
std::cout << (!(y != y) ? "true" : "false") << std::endl;
...

apl13

Ошибка компиляции будет и без assert.
Ну да.
Просто я специально это все вынес эти проверки вперед кода, чтобы было ближе к оригиналу на Хаскеле. Там-то это еще в строке с :: написано.
Оставить комментарий
Имя или ник:
Комментарий: