用字符串映射行为

时间:2019-07-26 14:33:27

标签: haskell functional-programming functor ramda.js

假设map为:

map :: (a -> b) -> [a] -> [b]

为什么R.map(R.toUpper, 'hello')返回['H', 'E', 'L', 'L', 'O']而不返回"HELLO"

例如,在haskell中,字符串是一个字符列表,因此map toUpper "hello"的行为符合预期(HELLO)。

Ramda的map会做同样的事情吗?


这可能是设计选择,但我认为Ramda的地图可能违反了函子定律: 如果我们将id函数映射到函子上,我们就不会取回原始函子

console.log(
  R.map(R.identity, 'Hello World'),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js" integrity="sha256-xB25ljGZ7K2VXnq087unEnoVhvTosWWtqXB4tAtZmHU=" crossorigin="anonymous"></script>

为什么我不期望map表现得更像:

const map = (fn, string) => string.replace(/./g, fn);


console.log(
  map(R.toUpper, 'hello world'),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js" integrity="sha256-xB25ljGZ7K2VXnq087unEnoVhvTosWWtqXB4tAtZmHU=" crossorigin="anonymous"></script>

1 个答案:

答案 0 :(得分:6)

正如评论所说,字符串不是functors。函子法要求

map :: Functor f => (a -> b) -> f a -> f b

也就是说,对于持有一个a类型的一个或多个项目的函子以及从a类型到b类型的函数,它将返回持有一个b类型的项目。字符串无法做到这一点,因为它仅包含字符。例如,您希望map(_ => 1.234, "hello")返回什么?

Ramda对字符串的行为不是故意的。正如Bergi所建议的那样,它根本无法实现。字符串看起来足够像数组(具有整数length属性和整数索引的子元素),因此代码将它们视为数组一样对待。

Ramda一直希望成为一个低级库,而创始人对编写手持代码并不特别感兴趣。如果您提供所需的类型,它应该可以像宣传的那样工作,但是如果您不提供,则几乎没有保证。但是,如果您对此有强烈的想法,请随时与Ramda团队raise an issue交流,甚至更好的是,raise a pull request以您喜欢的行为。它可能不会被接受,但会得到公平的听证。