用字符串映射行为
map behaviour with strings
假设 map
是:
map :: (a -> b) -> [a] -> [b]
为什么 R.map(R.toUpper, 'hello')
returns ['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>
正如评论所说,字符串不是 functor
s。函子法则要求
map :: Functor f => (a -> b) -> f a -> f b
也就是说,对于一个包含一个或多个类型 a
的函子和一个从类型 a
到类型 b
的函数,它将 return 一个函子拥有一个或多个 b
类型的物品。 String 不能这样做,因为它只包含字符。例如,您期望 map(_ => 1.234, "hello")
到 return 是什么?
Ramda 对字符串的行为不是故意的。正如 Bergi 所建议的那样,它只是脱离了实施。字符串看起来很像数组(具有整数 length
属性和整数索引子元素),代码将它们视为数组。
Ramda 一直打算做一个底层库,创始人对编写手持代码并不是特别感兴趣。如果您提供所需的类型,它应该像宣传的那样工作,但如果您不提供,则几乎没有任何保证。但是,如果您对此有强烈的感觉,请随意 raise an issue with the Ramda team about it, or even better, raise a pull request 采取您喜欢的行为。它可能不会被接受,但它会得到公平的听证会。
假设 map
是:
map :: (a -> b) -> [a] -> [b]
为什么 R.map(R.toUpper, 'hello')
returns ['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>
正如评论所说,字符串不是 functor
s。函子法则要求
map :: Functor f => (a -> b) -> f a -> f b
也就是说,对于一个包含一个或多个类型 a
的函子和一个从类型 a
到类型 b
的函数,它将 return 一个函子拥有一个或多个 b
类型的物品。 String 不能这样做,因为它只包含字符。例如,您期望 map(_ => 1.234, "hello")
到 return 是什么?
Ramda 对字符串的行为不是故意的。正如 Bergi 所建议的那样,它只是脱离了实施。字符串看起来很像数组(具有整数 length
属性和整数索引子元素),代码将它们视为数组。
Ramda 一直打算做一个底层库,创始人对编写手持代码并不是特别感兴趣。如果您提供所需的类型,它应该像宣传的那样工作,但如果您不提供,则几乎没有任何保证。但是,如果您对此有强烈的感觉,请随意 raise an issue with the Ramda team about it, or even better, raise a pull request 采取您喜欢的行为。它可能不会被接受,但它会得到公平的听证会。