我试图使用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
Run Code Online (Sandbox Code Playgroud)
作为Haskell的初学者,我无法知道如何为实例定义>> =运算符,使用我的函数来定义bind.
myReturn和myBind函数是否应该使用MyList而不是普通类型变量?如何正确定义>> =所需的包装和拆包?
我陷入了映射f的函数参数,其中f :: a - > [b],但似乎我需要f :: a - > MyList b,但是map不会接受它作为参数.
为混乱道歉.所有帮助表示赞赏
[我知道这里有一个类似的问题:重新定义列表monad实例,但我担心我不能按照那里的答案.]
您只需打开您的MyList类型,对其进行操作,然后将其重新包装:
instance Monad MyList where
return x = MyList [x]
(MyList xs) >>= f = MyList . concat . map unMyList . map f $ xs
Run Code Online (Sandbox Code Playgroud)
你可以(并且应该)将其浓缩MyList $ concatMap (unMyList . f) xs,但我已将其扩展用于说明目的.您可以通过定义自己的函数map和concat函数来简化此定义MyList:
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
Run Code Online (Sandbox Code Playgroud)
现在它看起来像普通的列表实例:
instance Monad [] where
return x = [x]
xs >>= f = concatMap f xs
Run Code Online (Sandbox Code Playgroud)