簡體   English   中英

Haskell:如何在自己的地圖數據類型上實現應用函子?

[英]Haskell: How can I implement an applicative functor on own map data type?

我對 Haskell 很陌生,我在 Haskell 中編寫了一個數據類型來表示區間映射。

這意味着什么? 簡而言之:一種地圖數據類型,它為每個可能的鍵返回一個值(在我的例子中簡單地說是 [0..])。

然后你插入“序列”,就像我希望我的地圖從 7 到 23 'b' 所以鍵 0 到 6 將是初始值,例如 'a' 和 7 到 23 將是 'b' 和 24 並且正在進行的將是 'a ' 再等等。

我設法編寫了數據類型、獲取和插入函數以及函子版本。

但是我無法使應用函子版本正常工作。 這個想法是將鍵值設置為 [0..] 並只處理這些值。

這是我的代碼,感謝您提供的任何幫助!

-- Building an interval map data structure in haskell

data IntervalMap k v = IntervalMap {keys :: [k] , values :: [v]} | Empty deriving Show
-- k = key, Typ variable 
-- v = value, Typ variable

singleton :: (Enum k, Num k) => v -> IntervalMap k v
singleton v = IntervalMap{keys=[0..], values= repeat v}

-- get operator => a ! 5 = value at position 5
(!) :: Ord k => IntervalMap k v -> k -> v
(!) iMap k = snd (head (filter (\(x, y) -> x == k) (zip (keys iMap) (values iMap)) ))

-- insert a sequence into intervalMap
insert :: (Ord k, Num k, Enum k) => k -> k -> v -> IntervalMap k v -> IntervalMap k v
insert start end value iMap = IntervalMap {keys=keys iMap, values = rangeChanger (values iMap) start end value}

-- helper function to change a range of values in an intervalMap
rangeChanger :: (Num a1, Enum a1, Ord a1) => [a2] -> a1 -> a1 -> a2 -> [a2]
rangeChanger iMapValues start end value = [if (i >= start) && (i <= end) then newValue else iMapValue | (iMapValue, newValue, i) <- zip3 iMapValues (repeat value) [0..]]


-- functor instance for intervalMap
instance Functor (IntervalMap k) where
    -- fmap :: (a -> b) -> f a -> f b 
    fmap f iMap = IntervalMap {keys=keys iMap, values= map f (values iMap) }


-- applicative functor for intervalMap
instance (Ord k, Num k, Enum k) => Applicative (IntervalMap k) where
pure k = IntervalMap{keys=[0..], values=repeat k}
_ <*> Nothing  = Nothing  
-- HOW TO DO?

-- class Functor functor => Applicative functor where
--  pure :: a -> functor a
--  (<*>) :: functor (a -> b) -> functor a -> functor b
--  (*>) :: functor a -> functor b -> functor b
--  (<*) :: functor a -> functor b -> functor a

似乎您總是希望鍵為[0..] ,例如它在您的rangeChanger函數中進行了硬編碼。 如果是這樣,那么它是多余的,老實說,我會把它排除在外。 您可以像在rangeChanger函數中那樣通過執行zip [0..] (values iMap)類的操作輕松地重建它。

如果您進行了更改,那么您的IntervalMap數據結構基本上與ZipList相同,后者在此處具有一個應用實例:

 instance Applicative ZipList where pure x = ZipList (repeat x) liftA2 f (ZipList xs) (ZipList ys) = ZipList (zipWith f xs ys)

您會看到這沒有定義<*>但可以根據liftA2來定義: p <*> q = liftA2 (\\fx -> fx) pq ,因此您也可以為ZipList顯式編寫它:

ZipList fs <*> ZipList xs = ZipList (zipWith (\f x -> f x) fs xs)

編輯:我還應該提到與ZipList一個區別是您的IntervalMap類型有一個Empty構造函數。 這讓事情變得更難,您需要知道您的值具有某種默認值,但這通常是不可能的(並非每個類型都有默認值),因此您的類型不能是 Applicative。 你真的需要那個Empty箱子嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM