重新定义monad列表实例

时间:2014-12-03 16:08:53

标签: haskell

我正在尝试使用newtype重新定义monad列表实例以创建包装列表类型,以便完全允许这样做,因为似乎无法覆盖Prelude定义。

到目前为止,我有以下内容:

newtype MyList a = MyList { unMyList :: [a] }
    deriving Show

myReturn :: a -> [a]
myReturn x = [x]

myBind ::  [a] -> (a -> [b]) -> [b]
myBind m f = concat $ map f m

instance Monad MyList where
    return x = MyList [x]
    xs >>= f = undefined

作为Haskell的初学者,我无法知道如何为实例定义>> =运算符,使用我的函数来定义bind。

myReturn和myBind函数是否应该使用MyList而不是普通类型变量?如何进行包装和拆包以定义>> =正确?

我陷入了映射f的函数参数,其中f :: a - > [b],但似乎我需要f :: a - > MyList b,但是map不会接受它作为参数。

为混乱道歉。所有的帮助表示赞赏。

[我知道这里有一个类似的问题:Redefine list monad instance但是我担心我无法在那里听到答案。]

1 个答案:

答案 0 :(得分:5)

您只需打开MyList类型,对其进行操作,然后将其重新包装:

instance Monad MyList where
    return x = MyList [x]
    (MyList xs) >>= f = MyList . concat . map unMyList . map f $ xs

您可以(并且应该)将此缩小为MyList $ concatMap (unMyList . f) xs,但我已将其展开以用于说明目的。您可以通过为map定义自己的concatMyList函数来简化此定义:

myMap :: (a -> b) -> MyList a -> MyList b
myMap f (MyList xs) = MyList $ map f xs

myConcat :: MyList (MyList a) -> MyList a
myConcat (MyList xs) = MyList $ concat $ map unMyList xs

myConcatMap :: (a -> MyList b) -> MyList a -> MyList b
myConcatMap f xs = myConcat $ myMap f xs

instance Monad MyList where
    return x = MyList [x]
    xs >>= f = myConcatMap f xs

现在它看起来像普通的列表实例:

instance Monad [] where
    return x = [x]
    xs >>= f = concatMap f xs