2016-07-28 5 views
1

У меня есть функция a, которая 1) вычисляет (argument+) argument и 2) удваивает ее (Interpreting Haskell monad example).Когда использовать или не использовать 'return' в выражении монады Haskell

a :: Int -> Int 
a = (id >>= (\n -> (n+))) >>= (\d -> return (d + d)) 

В этой функции я должен использовать возврат для предотвращения ошибок.

Однако в этой тройной функции, которая возвращает ((argument+) argument)+ argument), чтобы утроить входной аргумент. Я не могу использовать возврат.

triplex :: Int -> Int 
triplex = (id >>= (\n -> (n+))) >>= (\d -> (d+)) 

Из этих примеров, я думаю, просто правило return 1) мы используем return когда мы возвращаем значение, 2) мы не используем return, когда мы возвращаем частичную функцию. Но я не уверен, что это правильное понимание. Итак, есть ли правило за этим return в Haskell?

+3

well yes - 'return' используется для вытягивания значений в вашу монаду - как и любая другая функция, которую вы просто должны смотреть на типы (' return' - это не то, что вы знаете из C-подобных языков) - кроме этого: зачем использовать monad-instance of '(->) a' здесь вообще? это просто запутывает все - это какое-то упражнение? – Carsten

+1

см.: '\ N -> (n +)' уже имеет желаемый тип 'Int -> (Int -> Int)' (ваша монада есть '(->) Int') - но, конечно,' d + d' имеет (он имеет тип 'Int') - поэтому вы используете' return (d + d) = \ _ -> (d + d) '(помните' '' d-> ... 'в' >> = (\ d -> ...) 'нужно вернуть монадическое значение - это' Int -> a' здесь) – Carsten

+0

@Carsten: Хороший ответ, я думаю, вы можете ответить на вопрос, если я принимаю этот вопрос, если не появятся лучшие ответы вдоль. Кстати, я новичок в Haskell, поэтому я пытаюсь понять, что такое монада в Haskell. – prosseek

ответ

6

return функция в Haskell имеет мало общего с return ключевого слова в императивных языках программирования, это просто обычная функция с обычной сигнатуры типа:

return :: Monad m => a -> m a 

В принципе, return принимает любое старое значение и «подъемниками «Это в монаду. Это немного яснее, что делает эта функция при замене m с конкретным типом, как Maybe:

return :: a -> Maybe a 

Там только одна реализация функции выше, и это Just, так return = Just для Maybe монады.

В вашем случае вы используете функцию monad, (->) r, также часто называемую «читающей» монадой. Выполнение же замены, как с Maybe, мы получаем следующую подпись:

return :: a -> r -> a 

Эту функцию также имеет только одну реализацию, которая должна игнорировать свой второй аргумент и вернуть его первым. Это то, что делает const, поэтому return = const для функций.


Вопрос о том, «когда использовать return» является разумным, но она должна иметь больше смысла после понимания выше: вы должны использовать return когда возвращаемое значение из функции передается >>= не монадический , поэтому его нужно «снять». Например, следующее будет ошибка типа:

Just 3 >>= \x -> x + 1 

В частности, правая рука должна возвращать Maybe Int, но он возвращает только в Int. Таким образом, мы можем использовать return для получения значения правильного типа:

Just 3 >>= \x -> return (x + 1) 

Однако рассмотрит аналогичное выражение.В следующем случае, с помощью return будет ошибка типа:

Just [("a", 1), ("b", 2)] >>= \l -> lookup "c" 

Это потому, что результат функции lookup является уже значение Maybe Int, поэтому использование return будет производить Maybe (Maybe Int), что было бы неправильно.

Возвращаясь к вашему примеру с помощью функции монады, (n+) уже зависит от типа Int -> Int, поэтому использование return было бы неправильно (он будет производить функцию типа Int -> Int -> Int). Однако d + d - это всего лишь значение типа Int, поэтому вам нужно return, чтобы поднять значение в монаду.


Стоит отметить, что в обоих случаях, вы всегда можете заменить return с его основной реализации. Вы можете использовать Just вместо return при использовании монады Maybe, и вы можете использовать const вместо return при использовании функции monad. Тем не менее, есть две веские причины использовать return:

  1. return Использование позволяет писать функции, которые работают с более чем одним видом монады. То есть, return получает вас Полиморфизм.

  2. Это очень идиоматическое использовать return поднять простые значения в монадический тип, так что яснее и менее шумный, чтобы всегда видеть return вместо того, чтобы видеть много различных функций с разными именами.

Смежные вопросы