Zig*_*ggy 2 monads functional-programming maybe elm sanctuary
我离开了弗里斯比教授的"功能编程指南",似乎是对"可能"的错误概念.
我相信:
map(add1, Just [1, 2, 3])
// => Just [2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
我对上述指南的感觉是Maybe.map应该尝试调用Array.map数组,基本上是返回Just(map(add1, [1, 2, 3]).
当我尝试使用Sanctuary的Maybe类型,以及最近Elm的Maybe类型时,我很失望地发现他们都不支持这个(或者,也许,我不明白他们是如何支持的).
在保护区,
> S.map(S.add(1), S.Just([1, 2, 3]))
! Invalid value
add :: FiniteNumber -> FiniteNumber -> FiniteNumber
^^^^^^^^^^^^
1
1) [1, 2, 3] :: Array Number, Array FiniteNumber, Array NonZeroFiniteNumber, Array Integer, Array ValidNumber
The value at position 1 is not a member of ‘FiniteNumber’.
Run Code Online (Sandbox Code Playgroud)
在榆树,
> Maybe.map sqrt (Just [1, 2, 3])
-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm
The 2nd argument to function `map` is causing a mismatch.
4| Maybe.map sqrt (Just [1, 2, 3])
^^^^^^^^^^^^^^
Function `map` is expecting the 2nd argument to be:
Maybe Float
But it is:
Maybe (List number)
Run Code Online (Sandbox Code Playgroud)
同样地,我觉得我应该能够将a Just(Just(1))视为一种Just(1).另一方面,我的直觉[[1]]完全相反.显然,map(add1, [[1]])应该返回[NaN]而不是[[2]]或任何其他东西.
在Elm,我能够做到以下几点:
> Maybe.map (List.map (add 1)) (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
Run Code Online (Sandbox Code Playgroud)
这是我想要做的,但不是我想要做的.
应该如何映射Maybe List?
你有两个仿函数可以处理:Maybe和List.您正在寻找的是将它们结合起来的一些方法.您可以简化您按功能组合发布的Elm示例:
> (Maybe.map << List.map) add1 (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
Run Code Online (Sandbox Code Playgroud)
这实际上就是你说的是不是你张贴的例子的速记如何你想做到这一点.
保护区有一个compose功能,所以上面将表示为:
> S.compose(S.map, S.map)(S.add(1))(S.Just([1, 2, 3]))
Just([2, 3, 4])
Run Code Online (Sandbox Code Playgroud)
同样地,我觉得我应该能够将a
Just(Just(1))视为一种Just(1)
这可以通过使用来完成join从elm-community/maybe-extra包.
join (Just (Just 1)) == Just 1
join (Just Nothing) == Nothing
join Nothing == Nothing
Run Code Online (Sandbox Code Playgroud)
Sanctuary也有join功能,因此您可以执行以下操作:
S.join(S.Just(S.Just(1))) == Just(1)
S.join(S.Just(S.Nothing)) == Nothing
S.join(S.Nothing) == Nothing
Run Code Online (Sandbox Code Playgroud)
正如 Chad 所提到的,您希望转换嵌套在两个函子中的值。
让我们首先分别映射每个人以获得舒适:
> S.map(S.toUpper, ['foo', 'bar', 'baz'])
['FOO', 'BAR', 'BAZ']
> S.map(Math.sqrt, S.Just(64))
Just(8)
Run Code Online (Sandbox Code Playgroud)
让我们考虑一下地图的一般类型:
map :: Functor f => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
现在,让我们专门针对上述两种用途专门化这种类型:
map :: (String -> String) -> Array String -> Array String
map :: (Number -> Number) -> Maybe Number -> Maybe Number
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好。但是在您的情况下,我们想要映射 type 的值Maybe (Array Number)。我们需要一个这种类型的函数:
:: Maybe (Array Number) -> Maybe (Array Number)
Run Code Online (Sandbox Code Playgroud)
如果我们进行映射,S.Just([1, 2, 3])我们将需要提供一个函数,该函数将[1, 2, 3]内部值作为参数。所以我们提供给S.map的函数必须是 type 的函数Array (Number) -> Array (Number)。S.map(S.add(1))是这样的功能。将所有这些结合在一起,我们得出:
> S.map(S.map(S.add(1)), S.Just([1, 2, 3]))
Just([2, 3, 4])
Run Code Online (Sandbox Code Playgroud)