Haskell旨在鼓励匈牙利表示法吗?

时间:2014-11-09 15:24:45

标签: haskell

我正在学习Haskell并开始注意以下函数中的常见后缀:

debugM
mapM_
mapCE

其中称为匈牙利表示法。但与此同时,我可以使用类型类来编写非模糊代码,如:

show
return

由于像map这样的函数如此常见并且在很多上下文中使用,为什么不让类型检查器选择正确的多态版本mapfmapmapM,{ {1}}或mapM_

2 个答案:

答案 0 :(得分:25)

有一些"匈牙利符号",但它有很大的不同。简而言之,Haskell的类型系统消除了对大部分系统的需求。

map / mapM是一个很好的例子。这两个函数赋予完全相同的概念,但不能多态表示,因为对差异的抽象会非常嘈杂。所以我们选择匈牙利表示法。

要清楚,这两种类型是

map  ::            (a ->   b) -> ([a] ->   [b])
mapM :: Monad m => (a -> m b) -> ([a] -> m [b])

这些看似相似,所有mapM都是添加monad,但不一样。当您创建以下同义词时,将显示该结构

type Arr    a b = a ->   b
type Klei m a b = a -> m b

并将类型重写为

map  ::            Arr    a b -> Arr    [a] [b]
mapM :: Monad m => Klei m a b -> Klei m [a] [b]

需要注意的是,ArrMonad 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

但事实证明,通过使用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)

所以为了简单起见,我们使用匈牙利表示法来区分类别,而不是将其汇总到Haskell的多态性功能中。

[0]值得注意的是,Klei m是一个类别意味着m是一个单子,而且类别法则完全符合monad法则。特别是,这是我记住monad法律的最佳方式。

[1]从技术上讲,Functor的唯一方法称为fmap而不是map,但它可能也许应该只被称为map。添加了f,以便map的类型签名保持简单(专用于列表),因此对初学者来说有点不那么令人生畏了。这是否是正确的决定是一场持续至今的辩论。

答案 1 :(得分:8)

你的假设是所有这些都大致相同 - 他们没有。 mapfmap几乎是相同的功能 - mapfmap专门用于[]仿函数(由于历史原因,或者初学者会得到更少混淆的类型错误 - 我不确定。)

另一方面,

mapMmapM_分别为map,后跟sequencesequence_ - 而他们正在做的事情看起来可能相关,他们正在做不同的事情。顺便说一下,对于monad来说,行为类似于fmap的函数是fmap(由于历史原因,它也会使用liftM的专用签名别名),Monad根据定义,s也是Functor s;请注意,现在这不是标准库所强制执行的 - 如果我没有弄错的话,应该用GHC 7.10纠正历史疏忽。

我不知道该告诉你关于debugMmapCE的内容,因为我之前没有看过这些内容。