简体   繁体   English

重新定义monad列表实例

[英]Redefining monad list instance

I am attempting to redefine the monad list instance using newtype to create a wrapped list type, so as to allow this to be done at all, since it seems the Prelude definitions are unable to be overridden. 我试图使用newtype重新定义monad列表实例,以创建一个包装列表类型,以便完全做到这一点,因为似乎Prelude定义无法被覆盖。

So far I have the following: 到目前为止,我有以下内容:

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

As a beginner in Haskell, I am at a loss to know how to define the >>= operator for the instance, using my function for the definition of bind. 作为Haskell的初学者,我不知所措,不知道如何使用我的函数为bind定义实例的>> =运算符。

Should the myReturn and myBind functions have types using MyList rather than plain type variables? myReturn和myBind函数应该使用MyList而不是普通类型变量来具有类型吗? How does one do the packing and unpacking necessary to define >>= properly? 如何正确定义>> =所需的打包?

I am getting stuck on the function argument to map f, where f :: a -> [b], but it seems I need f :: a -> MyList b, but then map won't accept that as an argument. 我被困在映射f的函数参数上,其中f :: a-> [b],但似乎我需要f :: a-> MyList b,但是map不会接受它作为参数。

Apologies for the confusion. 抱歉造成混乱。 All assistance appreciated. 感谢所有协助。

[I am aware there is a similar question here: Redefine list monad instance but I'm afraid I cannot follow the answers there.] [我知道这里有一个类似的问题: 重新定义列表monad实例,但我恐怕无法在那里找到答案。]

You simply need to unwrap your MyList type, operate on it, then wrap it back up: 您只需要解开MyList类型,对其进行操作,然后将其包装起来即可:

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

You can (and should) condense this to MyList $ concatMap (unMyList . f) xs , but I've left it expanded for illustrative purposes. 您可以(并且应该)将此压缩MyList $ concatMap (unMyList . f) xs ,但出于说明目的,我将其扩展了。 You could simplify this definition by defining your own map and concat functions for MyList : 您可以通过为MyList定义自己的mapconcat函数来简化此定义:

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

And now it looks like the normal list instance: 现在,它看起来像普通的列表实例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM