在Maybe / List monad中如何实现`join`?

时间:2019-07-26 11:21:05

标签: haskell monads

>>=可以根据join :: Monad m => m (m a) -> m a join m = m >>= id 定义实现:

join Nothing = Nothing
join (Just (Just x)) = Just x

具体来说,如何在Maybe和List单子中实现它?

可能在monad中吗?

join [] = []
join [[xs]] = [xs]

并在列表单子中:

sudo: unable to stat /etc/sudoers: Permission denied
sudo: no valid sudoers sources found, quitting
sudo: unable to initialize policy plugin

谢谢。

3 个答案:

答案 0 :(得分:5)

join仅实现一次 ,并且适用于所有Monad类型。

Monad抽象的重点是允许以相同的方式处理不同类型。一旦为您的类型提供了>>=(和return),并确保它们遵循Monad法则,任何通用的足以仅使用这些操作的代码都将在您的类型上正常工作。

答案 1 :(得分:4)

join只是一个常规函数,根据预先存在的(>>=)函数实现。您不必担心使用了哪个 monad。 (>>=)会解决这个问题。

相反,Monad 可以的定义更接近其数学定义:

class Monad' m where
    return :: a -> m a
    join :: m (m a) -> m a

使用

(>>=) :: Monad' m => m a -> (a -> m b) -> m b
x >>= f = join (fmap f x)

作为常规功能。这样,join的列表特定定义将仅为concat :: [[a]] -> [a]

instance Monad' [] where
    return x = [x]
    join = concat

答案 2 :(得分:3)

join只是implemented as [src]

join              :: (Monad m) => m (m a) -> m a
join x            =  x >>= id

如果我们查看[] [src]Maybe [src]的monad实例,就会看到:

instance Monad []  where
    {-# INLINE (>>=) #-}
    xs >>= f             = [y | x <- xs, y <- f x]
    {-# INLINE (>>) #-}
    (>>) = (*>)
    {-# INLINE fail #-}
    fail _               = []
instance  Monad Maybe  where
    (Just x) >>= k      = k x
    Nothing  >>= _      = Nothing

    (>>) = (*>)

    fail _              = Nothing

因此,对于列表,join等效于:

-- for lists
   join xs
-> xs >>= id
-> [ y | x <- xs, y <- id x ]
-> concatMap id xs
-> concat xs

因此对于列表,等效的实现是:

join_list :: [[a]] -> [a]
join_list = concat

对于Maybe,我们可以进行案例分析:输入为Maybe (Maybe a),因此这里基本上存在三种可能性:

-- (1)
   join Nothing
-> Nothing >>= id
-> Nothing

-- (2)
   join (Just Nothing)
-> Just Nothing >>= id
-> id Nothing
-> Nothing

-- (3)
   join (Just (Just x))
-> Just (Just x) >>= id
-> id (Just x)
-> Just x

因此,对于Maybe来说,等效实现为:

join_maybe :: Maybe (Maybe a) -> Maybe a
join_maybe (Just x) = x
join_maybe Nothing = Nothing
因此,

join不会重新实现用于列表或Maybe单子,它只是将实现用于(>>=)用于列表和Maybe,并且由于这些不同,join的行为当然也不同。