Как я должен нанести на карту Возможно Список?

Я отказался от "Адекватного руководства по функциональному программированию" профессора Фрисби с тем, что кажется неправильным представлением о Возможно.

Я верю:

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
Другие вопросы по тегам