2014-12-03 58 views
1

我試圖重新定義monad列表實例使用newtype來創建一個包裝列表類型,以便完成這一切,因爲它看起來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 

作爲哈斯克爾初學者,我很茫然知道如何界定>> =運算符的情況下,用我的函數的定義綁定。

myReturn和myBind函數應該使用MyList而不是普通類型變量的類型嗎?如何正確定義>> =來進行打包和拆包?

我陷入函數參數映射f,其中f :: a - > [b],但它似乎我需要f :: a - > MyList b,但然後映射將不會接受爲一個論點。

道歉的混亂。所有協助表示讚賞

[我知道有一個類似的問題在這裏:Redefine list monad instance但我怕我跟不上答案有]

+1

你爲什麼要包裝清單以這樣的方式?爲什麼不使用'data List t = Empty |創建一個新的單鏈表t:+(List t)',然後以這種方式重新定義 - 當然這是一個更實用的練習,同樣具有挑戰性? – AJFarmar 2014-12-03 16:36:54

回答

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,但我把它擴大用於說明目的。你可以定義自己的mapconcat功能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 

而現在它看起來像正常的列表實例:

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

我建議派生'Functor',然後'myMap = fmap' – 2014-12-03 18:05:15

+0

@SassaNF這也是我會推薦的,但在這種情況下,我想專注於monad實例。不過,這將是一個相當微不足道的變化。 – bheklilr 2014-12-03 19:55:47

+0

是的,我同意;但可能是話題的重要重疊。 'a >> = f =連接$ fmap f a' – 2014-12-03 20:08:52