我正在努力了解Functors的工作原理,所以我在这里阅读:http://learnyouahaskell.com/making-our-own-types-and-typeclasses#the-functor-typeclass
我有一个函数,它采用一个映射并计算值的总和(这是一个列表).
reduce :: Map String [Int] -> Map String Int
reduce = fmap sum
Run Code Online (Sandbox Code Playgroud)
我真的不明白它是如何fmap工作的所以我读了它并试图制作我自己的版本.我无法真正测试它,因为Map已在Haskell库中定义.
这是对的吗?
instance Functor (Map k) where
fmap f fromList[] = []
fmap f fromList[(k, v): xs] = (f v) fmap xs
Run Code Online (Sandbox Code Playgroud)
你的榜样在道德上是正确的,但它有一些错误.最明显的是你不能模式匹配,fromList ...因为fromList它不是构造函数.Data.Map模块不会导出实际的构造函数,因此我们根本不能进行模式匹配 - 这是为了确保您不能访问该模块中使用的内部树表示并可能破坏某些不变量.
一个更好的例子可能是例如(约束Ord k是必需的Map,如@gallais提到的那样)
instance Ord k => Functor (Map k) where
fmap f m = fromList (map modify (toList m))
where modify (k,v) = (k, fv)
Run Code Online (Sandbox Code Playgroud)
这基本上将整个地图转换为由键值对组成的关联列表,然后更改应用的每个值f,然后重新生成Map.更简洁,它可以写成
instance Ord k => Functor (Map k) where
fmap f = fromList . map (\(k,v) -> (k,f v)) . toList
Run Code Online (Sandbox Code Playgroud)
请记住,这不是非常有效 - Map模块中的实际实例不必通过中间列表.
最后,请注意您无法定义自己的实例,因为Map模块已经为您提供了一个实例.如果您真的想要试验它,可以声明newtype:
newtype MyMap k v = MyMap { unMyMap :: Map k v }
instance Functor (MyMap k) where
fmap f = MyMap . fromList . map (\(k,v) -> (k,f v)) . toList . unMyMap
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
382 次 |
| 最近记录: |