【问题标题】:Haskell: How can I implement an applicative functor on own map data type?Haskell:如何在自己的地图数据类型上实现应用函子?
【发布时间】:2021-06-20 10:04:46
【问题描述】:

我对 Haskell 很陌生,我在 Haskell 中编写了一个数据类型 用于表示区间图。

这是什么意思?简而言之:一种为您返回值的地图数据类型 对于每个可能的键(在我的例子中简单地说 [0..])。

然后你插入“序列”,就像我希望我的地图保持从 7 到 23 'b' 所以键 0 到 6 将是初始值,例如'a' 和 7 到 23 将是 'b' 和 24 和正在进行的将再次是 'a' 等等。

我设法编写了数据类型、一个 get 和 insert 函数以及一个 函子版本。

但我无法让应用函子版本工作。 我们的想法是将键值设置为 [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

【问题讨论】:

  • 不应该puresingleton 相同,即repeat k 而不是[k]
  • 是的,你是对的。那是我的错

标签: dictionary haskell functor applicative


【解决方案1】:

您似乎总是希望密钥是[0..],例如它被硬编码在您的 rangeChanger 函数中。如果是这样,那么它是多余的,老实说,我会把它排除在外。您可以通过像在 rangeChanger 函数中所做的那样执行 zip [0..] (values iMap) 之类的操作来轻松地重建它。

如果您进行该更改,那么您的 IntervalMap 数据结构与具有应用实例 hereZipList 基本相同:

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

你看到这并没有定义&lt;*&gt;,但它可以用liftA2定义:p &lt;*&gt; q = liftA2 (\f x -&gt; f x) p q,所以你也可以明确地为ZipList写:

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

编辑:我还应该提到 ZipList 的一个区别是您的 IntervalMap 类型有一个 Empty 构造函数。这使事情变得更加困难,您需要知道您的值具有某种默认值,但这通常是不可能的(并非每种类型都有默认值),因此您的类型不能是 Applicative。你真的需要那个Empty 箱子吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多