Как я должен нанести на карту Возможно Список?
Я отказался от "Адекватного руководства по функциональному программированию" профессора Фрисби с тем, что кажется неправильным представлением о Возможно.
Я верю:
map(add1, Just [1, 2, 3])
// => Just [2, 3, 4]
Я чувствую отход от вышеупомянутого руководства в том, что Maybe.map
должен попытаться позвонить Array.map
по массиву, по сути, возвращая Just(map(add1, [1, 2, 3])
,
Когда я попробовал это с использованием типа " Святилище" и, возможно, совсем недавно, типа " Вяза", я был разочарован, обнаружив, что ни один из них не поддерживает это (или, возможно, я не понимаю, как они поддерживают это).
В святилище,
> 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’.
В Вязах
> 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)
Точно так же я чувствую, что должен уметь лечить 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)
Что я и хочу сделать, но не так, как я хочу.
Как следует составить карту над списком "Возможно"?
2 ответа
Как упоминал Чад, вы хотите преобразовать значения, вложенные в два функтора.
Давайте начнем с сопоставления каждого отдельно, чтобы освоиться:
> S.map(S.toUpper, ['foo', 'bar', 'baz'])
['FOO', 'BAR', 'BAZ']
> S.map(Math.sqrt, S.Just(64))
Just(8)
Давайте рассмотрим общий тип карты:
map :: Functor f => (a -> b) -> f a -> f b
Теперь давайте специализируем этот тип для двух вышеупомянутых применений:
map :: (String -> String) -> Array String -> Array String
map :: (Number -> Number) -> Maybe Number -> Maybe Number
Все идет нормально. Но в вашем случае мы хотим отобразить значение типа Maybe (Array Number)
, Нам нужна функция с этим типом:
:: Maybe (Array Number) -> Maybe (Array Number)
Если мы на карте S.Just([1, 2, 3])
нам нужно будет предоставить функцию, которая принимает [1, 2, 3]
Внутренняя ценность - как аргумент. Таким образом, функция, которую мы предоставляем S.map
должна быть функцией типа 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])
У вас есть два функтора: Maybe
а также List
, То, что вы ищете, это способ объединить их. Вы можете упростить пример Elm, который вы разместили, с помощью композиции функций:
> (Maybe.map << List.map) add1 (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
На самом деле это всего лишь краткий пример того, что вы опубликовали пример, который, как вы сказали, не был тем, как вы хотели это сделать.
Святилище имеет compose
функция, так что выше будет представлен как:
> S.compose(S.map, S.map)(S.add(1))(S.Just([1, 2, 3]))
Just([2, 3, 4])
Точно так же я чувствую, что должен уметь лечить
Just(Just(1))
какJust(1)
Это можно сделать с помощью join
от elm-community/maybe-extra
пакет.
join (Just (Just 1)) == Just 1
join (Just Nothing) == Nothing
join Nothing == Nothing
Святилище имеет join
функция, так что вы можете сделать следующее:
S.join(S.Just(S.Just(1))) == Just(1)
S.join(S.Just(S.Nothing)) == Nothing
S.join(S.Nothing) == Nothing