我正在学习Haskell并开始注意以下函数中的常见后缀:
debugM
mapM_
mapCE
Run Code Online (Sandbox Code Playgroud)
这被称为匈牙利表示法.但与此同时,我可以使用类型类来编写非模糊代码,如:
show
return
Run Code Online (Sandbox Code Playgroud)
因为喜欢功能map是如此普遍,在很多情况下使用时,为什么不让类型检查挑选的正确版本的多态性map,fmap,mapM,mapM_或mapCE?
J. *_*son 25
有一点"匈牙利符号",但它有很大的不同.简而言之,Haskell的类型系统消除了对大部分系统的需求.
该map/ mapM事情是一个整洁的例子.这两个函数赋予完全相同的概念,但不能多态表示,因为对差异的抽象会非常嘈杂.所以我们选择匈牙利表示法.
需要说明的是,这两种类型
map :: (a -> b) -> ([a] -> [b])
mapM :: Monad m => (a -> m b) -> ([a] -> m [b])
Run Code Online (Sandbox Code Playgroud)
这些看起来很相似,都是mapM添加monad,但不一样.当您创建以下同义词时,将显示该结构
type Arr a b = a -> b
type Klei m a b = a -> m b
Run Code Online (Sandbox Code Playgroud)
并将类型重写为
map :: Arr a b -> Arr [a] [b]
mapM :: Monad m => Klei m a b -> Klei m [a] [b]
Run Code Online (Sandbox Code Playgroud)
需要注意的一点是,Arr与Monad m => Klei m通常极为相似的事情.它们都形成一种称为"类别"的特定结构,它允许我们在其中提升各种计算.[0]
我们想要的是用类似的东西来抽象类别的选择
class Mapping cat where
map :: cat a b -> cat [a] [b]
instance Mapping (->) where map = Prelude.map
instance Monad m => Mapping (Klei m) where map = mapM -- in spirit anyway
Run Code Online (Sandbox Code Playgroud)
但事实证明,通过使用Functor[1] 抽象列表部分可以获得更多的收益
class Functor f where
map :: (a -> b) -> (f a -> f b)
instance Functor [] where
map = Prelude.map
instance Functor Maybe where
map Nothing = Nothing
map (Just a) = Just (f a)
Run Code Online (Sandbox Code Playgroud)
因此,为了简单起见,我们使用匈牙利表示法来区分类别,而不是将其汇总到Haskell的多态性功能中.
[0]值得注意的是,Klei m类别暗示的事实是m单子行为,类别法则完全符合单一法则.特别是,这是我最喜欢记住monad法则的方法.
[1]从技术上讲,唯一的方法Functor是fmap不被称为map,但它可能也许应该被称为公正map.在f加入使得对于类型签名map仍然很简单(专门用于列表),因此是有点那么吓人初学者.这是否是正确的决定是一场持续至今的辩论.
你的假设是所有这些都大致相同 - 他们没有.map并且fmap几乎是相同的功能 - map仅fmap适用于[]仿函数(由于历史原因,或者初学者会减少混淆类型错误 - 我不确定).
mapM而mapM_另一方面,就像是map接着sequence或sequence_分别 - 虽然他们所做的事情可能看起来很相关,但他们正在做不同的事情.顺便说一句,fmap对于monad来说,行为类似的函数是...... fmap(liftM由于历史原因,它也有专门的签名别名),因为Monad根据定义,Functors 也是s; 请注意,目前这不是标准库所强制执行的 - 如果我没有弄错的话,应该用GHC 7.10纠正这一历史疏忽.
我不知道该告诉你什么debugM,mapCE因为我以前没见过这些.