【发布时间】:2015-12-30 18:20:34
【问题描述】:
在学习了 Haskell 中的 monad 之后——这个主题对于所有暗示都非常有吸引力——我想知道我是否可以在不使用已经定义的类型类的情况下自己定义一个 monad。
我不想让Monad 成为Functor 的实例,我只想定义一个monad 本身,它有自己的fmap 函数(另外我想更改一些函数名称,例如return 并调用它unit)。
monad 可以由绑定运算符(>>=) 和函数return 定义,但也可以用return 和join 定义,因为最后一个函数可以用绑定运算符:join m = m >>= id。所以一个单子可以(技术上)用return和join定义,仅此而已。函数fmap 是必需的(以及在Haskell 中存在Functor 的基础),但也可以根据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 = return . f- 这不起作用。return . f的类型是a -> m b,而不是m a -> m b。mapper也不起作用:您不能在id或∘上进行模式匹配,除非您将它们定义为 数据构造函数。 — 无论如何...我不太明白你在这里想要达到什么目的。从根本上说,monad 首先是一个函子。即使在技术上可以省略该要求,也不意味着这样做是有意义的。 Haskell98 做到了,很快就意识到这不是一个好主意。 -
(g <$>) = (return . g =<<),即return是不够的,还需要bind。(k =<<) = join . (k <$>),所以你必须有(<$>)(即fmap)和join。参看。 stackoverflow.com/questions/34545818/…