假设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>
答案 0 :(得分:6)
正如评论所说,字符串不是functor
s。函子法要求
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以您喜欢的行为。它可能不会被接受,但会得到公平的听证。