鉴于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函数映射到函子上,我们就不会取回原始函子
map :: (a -> b) -> [a] -> [b]
console.log(
R.map(R.identity, 'Hello World'),
);
我为什么不期望map
表现得更像:
const map = (fn, string) => string.replace(/./g, fn);
console.log(
map(R.toUpper, 'hello world'),
);
Scott Sauyet.. 7
就像评论所说,Strings不是functor
s。函子法要求
map :: Functor f => (a -> b) -> f a -> f b
也就是说,对于持有一个或多个类型的项a
和一个函数从一个类型a
到另一个类型b
的函子,它将返回持有一个或多个类型的项的相同类型的函子b
。字符串无法做到这一点,因为它仅包含字符。例如,您希望map(_ => 1.234, "hello")
返回什么?
Ramda在Strings上的行为不是故意的。正如Bergi所建议的那样,它根本无法实现。字符串看起来足够像数组(具有整数length
属性和整数索引的子元素),因此代码将它们视为数组一样对待。
Ramda一直希望成为一个低级库,而创始人对编写手持代码并不特别感兴趣。如果您提供所需的类型,它应该可以像宣传的那样工作,但是如果您不提供,则几乎没有保证。但是,如果您对此有强烈的感觉,请随时向Ramda团队提出有关此问题的信息,或者甚至更好地针对您希望的行为提出拉式请求。它可能不会被接受,但是会得到公平的听证。
就像评论所说,Strings不是functor
s。函子法要求
map :: Functor f => (a -> b) -> f a -> f b
也就是说,对于持有一个或多个类型的项a
和一个函数从一个类型a
到另一个类型b
的函子,它将返回持有一个或多个类型的项的相同类型的函子b
。字符串无法做到这一点,因为它仅包含字符。例如,您希望map(_ => 1.234, "hello")
返回什么?
Ramda在Strings上的行为不是故意的。正如Bergi所建议的那样,它根本无法实现。字符串看起来足够像数组(具有整数length
属性和整数索引的子元素),因此代码将它们视为数组一样对待。
Ramda一直希望成为一个低级库,而创始人对编写手持代码并不特别感兴趣。如果您提供所需的类型,它应该可以像宣传的那样工作,但是如果您不提供,则几乎没有保证。但是,如果您对此有强烈的感觉,请随时向Ramda团队提出有关此问题的信息,或者甚至更好地针对您希望的行为提出拉式请求。它可能不会被接受,但是会得到公平的听证。