Комментарии 24
Наверное всё-таки:
:)
В Dive Into Python «list comprehension» перевели как «расширенная запись списков».
- instance MyEq Bool where
- myEqual True True = True
- myEqual False False = True
- myEqual _ _ = False
:)
В Dive Into Python «list comprehension» перевели как «расширенная запись списков».
0
Про типы и классы типов могу посоветовать соответсвующую главу «Making Our Own Types and Typeclasses» из «Learn You a Haskell for Great Good!».
0
>> foo :: (Eq a, Show a, Read a) => a -> String -> String
Как это сделать, например, в С++/C#?
ну, в C# можно с помощью generics и type constraints:
Как это сделать, например, в С++/C#?
ну, в C# можно с помощью generics и type constraints:
public void Foo (T a) where T : IEquable, IShowable, IReadable
0
Подозревал об этом, когда писал, но не проверил.
Буду иметь в виду.
Буду иметь в виду.
0
с generics вообще много фана, т.к. они похожи на typeclasses
вот, к примеру:
чем не монада? :)
( devhawk.net/2008/07/30/Monadic+Philosophy+Part+2+The+LINQ+Monad.aspx )
вот, к примеру:
var Orders = new List<Order>() //code to populate orders omitted var q = Orders .Where(x => x.OrderDate < DateTime.Now) .OrderBy(x => x.OrderDate) .Select(x => new {ID = x.OrderID, Date = x.OrderDate})
чем не монада? :)
( devhawk.net/2008/07/30/Monadic+Philosophy+Part+2+The+LINQ+Monad.aspx )
0
Имхо, проводить аналогию между монадами и вычислениями — плохая идея, хоть и популярная. У меня, например, сразу возникло непонимание: вычисления — это функции, чем они не подходят? Мне было бы понятнее, если бы монады представляли как контейнеры.
0
А функции подходят, только это частный случай, когда результат предыдущего вычисления просто передаётся следующей функции.
0
Код забыл:
runIdentity $ do
x <- return 5
y <- return $ x + 4
return $ y * 2
0
Вот об этом я и говорю — своершенно неочевидно, что нам мешает написать:
x = 5
y = x + 4
x = 5
y = x + 4
0
Честно, не нашёлся, что ответить.
Что мешает нам использовать напрямую класс в ООП и заставляет нас описывать какой-то интерфейс?
Ничего не мешает, это просто удобная абстракция. В частном случае можно вызывать функции. Но это один частный случай.
Что мешает нам использовать напрямую класс в ООП и заставляет нас описывать какой-то интерфейс?
Ничего не мешает, это просто удобная абстракция. В частном случае можно вызывать функции. Но это один частный случай.
0
Мешает то, что таким образом мы лишаем себя возможности легко подставлять разные имплементации. И об этом стоит четко говорить при объяснении ООП. А здесь в чем проблема?
0
Причем с функциями, возвращающими
Maybe
не показателен?0
Показателен, как и с ио, состоянием, массивами, ошибками, итд — но это все воспринимается как частные случаи. Типа — придумали библиотеку и под нее все подгоняем.
Нужно более общее восприятие. Например, начнем с функтора. Зачем он нам нужен? Чтобы навешивать дополнительную логику к применению функции.
Если x — простое значение, мы пишем «f x»; если x — функтор, мы пишем «fmap f x». Что оно делает?
Для x :: [a] — применяет f ко всем элементам x.
Для x :: Maybe a — применяет f к содержимому, если оно есть, Nothing остается Nothing.
Для x :: IO a — применяет f к будущему значению, которое мы получим в результате ввода.
Для x :: Tree a — применяет f к значениям во всех узлам дерева.
Для x :: (твой тип) a — сам определишь, что оно делает.
Однако что делать, если функция возвращает значение, которое само по себе функтор? Мы получим нагромождение функторов — [[a]], Maybe Maybe a, IO IO a, Tree Tree a. Таким образом, полезно иметь также функцию, которая схлопывает двойной функтор в одинарный — join.
Аналогично, нам нужна функция для помещения значения в функтор — return.
Вот функтор с join и return — и есть монада. А про bind можно и потом рассказать, с примерами почему он удобен.
Нужно более общее восприятие. Например, начнем с функтора. Зачем он нам нужен? Чтобы навешивать дополнительную логику к применению функции.
Если x — простое значение, мы пишем «f x»; если x — функтор, мы пишем «fmap f x». Что оно делает?
Для x :: [a] — применяет f ко всем элементам x.
Для x :: Maybe a — применяет f к содержимому, если оно есть, Nothing остается Nothing.
Для x :: IO a — применяет f к будущему значению, которое мы получим в результате ввода.
Для x :: Tree a — применяет f к значениям во всех узлам дерева.
Для x :: (твой тип) a — сам определишь, что оно делает.
Однако что делать, если функция возвращает значение, которое само по себе функтор? Мы получим нагромождение функторов — [[a]], Maybe Maybe a, IO IO a, Tree Tree a. Таким образом, полезно иметь также функцию, которая схлопывает двойной функтор в одинарный — join.
Аналогично, нам нужна функция для помещения значения в функтор — return.
Вот функтор с join и return — и есть монада. А про bind можно и потом рассказать, с примерами почему он удобен.
0
Это ближе к теории категорий, но зато дальше от
Какое объяснение проще понять — не знаю, надо опрос проводить, лично мне были наиболее понятны те, что приведены по ссылкам.
do
-нотации. В итоге всё равно придётся рассказывать про вычисления, которые комбинируется bind'ом неявно внутри do
и что там можно использовать любую монаду.Какое объяснение проще понять — не знаю, надо опрос проводить, лично мне были наиболее понятны те, что приведены по ссылкам.
0
а мне наоборот кажется более удобным представлять себе монаду, как контейнер содержащий в себе не значение, но «замороженный процесс» его вычисления. Это во многом согласуется с тем, что теоретик-первопроходец Eugenio Moggi в далёком 89 году предложил использовать монады именно для формализации «понятия вычисления» (notion of computation).
вот как, например, представить себе монаду Cont, как контейнер?
вот как, например, представить себе монаду Cont, как контейнер?
+2
ну дык, следующий раз так и не настал?
0
Сори что не по теме, перечитывал статью — наткнулся на «значниею», поправьте плиз.
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Классы типов, монады