После изучения монад в Haskell - предмета, который очень привлекателен для всего, что подразумевается, - интересно, смогу ли я определить монаду самостоятельно, не используя уже определенные типы классов.Определение монады с нуля в Haskell
Вместо того, чтобы Monad
Экземпляр Functor
, я просто хочу, чтобы определить монады само по себе, с его собственной fmap
функции (Кроме того, я хотел бы изменить некоторые имена функций, таких как return
и называют его unit
).
Монады может быть определен оператором (>>=)
связывания и функциями return
, но она также может быть определен в терминах return
и join
с этого последней функции он может быть выражен в терминах оператора связывания: join m = m >>= id
. Таким образом, монада может быть (технически) определена в терминах return
и join
и ничего больше. Требуется функция fmap
(и основание существования Functor
в Haskell), но также может быть определена в терминах return
, так как она может быть определена также (я думаю) следующим образом: fmap f m = m >>= return . f
(перед редактированием было написано, fmap f m = return . f
, это была опечатка).
Но я знаю, что это будет не так эффективно, как использовать предопределенный класс Monad
, это просто лучше понять язык Haskell.
Как это сделать? Это описание этой концепции из моей головы, прямо сейчас, так что это не полезно код:
-- Just a sketch
infixr 9 ∘
(∘) :: (b -> c) -> (a -> b) -> a -> c
(∘) g f x = g (f x)
--(f ∘ g) x = f (g x)
-- My own 'fmap'
--mapper id = id
--mapper (f ∘ g) = mapper f ∘ mapper g
-- My monad
class MyMonadBase (m :: * -> *) where
unit :: a -> m a --return
join :: m (m a) -> m a
join = (>>= id)
mapper f m = m >>= unit ∘ f
--Testing:
data Tree a = Leaf a | Branch (Tree a) (Tree a)
instance MyMonadBase Tree where
unit = Leaf
join (Leaf x) = x
join (Branch l r) = Branch (join l) (join r)
ли я в правильном направлении (концептуально)?
'fmap f = возврат. f' - это не работает. Тип 'return. f' является 'a -> m b', а не' m a -> m b'. Также не работает «mapper»: вы не можете сопоставлять шаблоны на 'id' или' ∘', если вы не определяете их как _data constructors_. - В любом случае ... Я не совсем понимаю, чего вы пытаетесь достичь здесь. Монада, по сути, прежде всего функтор. Даже если это технически возможно опустить это требование, это не значит, что имеет смысл это сделать. Haskell98 сделал, и было быстро понято, что это не очень хорошая идея. – leftaroundabout
'(g <$>) = (return. G = <<)', то есть 'return' недостаточно, вам также понадобится привязка для этого. '(k = <<) = join. (k <$>) ', поэтому вы должны иметь' (<$>) '(т. е.' fmap') с 'join'. ср http://stackoverflow.com/questions/34545818/is-monad-bind-operator-closer-to-function-composition-chaining-or-functi/34561605#34561605 –