Не понимаю, когда я должен использовать let
, и когда мне нужно использовать привязку <-
.В чем разница между блоками <- и "let" внутри блоков?
ответ
<-
является >>=
(bind
), где let
является fmap
в do
блоке.
Кража пример из here:
do x1 <- action1 x0
x2 <- action2 x1
action3 x1 x2
-- is equivalent to:
action1 x0 >>= \ x1 -> action2 x1 >>= \ x2 -> action3 x1 x2
action1
, action2
& action3
возвращают какое-то монады, говорят:
action1 :: (Monad m) => a -> m b
action2 :: (Monad m) => b -> m c
action3 :: (Monad m) => b -> c -> m d
Вы можете переписать пусть привязок, как например:
-- assume action1 & action3 are the same
-- but action2 is thus:
action2 :: b -> c
do
x1 <- action1 x0
let x2 = action2 x1
action3 x1 x2
do
x1 <- action1 x0
x2 <- return & action2 x1
action3 x1 x2
-- of course it doesn't make sense to call action2
-- an action anymore, it's just a pure function.
let
дает имя для вызова функции.
<-
связывает результат монадической операции в текущей монаде с именем.
Они совсем разные. Используйте let
для результатов функций вне монады, то есть нормальных чистых функций. Используйте <-
для любого монадического, так как он «разворачивает» результат монады и позволяет вам получить значение внутри него.
Например:
предположить функцию IO со следующей подписью
frobnicate :: String -> IO Bool
и чистой функции
dothing :: Bool -> Bool
мы можем сделать это
main :: IO()
main = do
x <- frobnicate "Hello"
let y = frobnicate "Hello"
-- z <- dothing x
let z = dothing x
return()
и мы знать т hat x :: Bool
, потому что Bool
был извлечен из результата операции IO
для нас (операция выполняется, и результат называется x
, поэтому мы можем использовать его позже).
Мы также знаем, что y :: IO Bool
- операция не была выполнена, это потенциал для операции ввода-вывода в будущем. Таким образом, единственная полезная вещь, которую мы можем сделать с y
, запускается позже, связывает результат и получается с Bool
внутри этого пути, но после let
, что Bool
еще не существует.
Третья строка закомментирована, потому что она не будет компилироваться - вы не можете выполнить монадическое связывание с операцией, которая не находится в соответствующей монаде. dothing
не возвращает IO
ничего, поэтому вы не можете связать его внутри функции IO()
.
Четвертая линия проста - z
сделан, чтобы быть результатом dothing x
, где x
было значение распакованного запуска frobnicate "Hello"
ранее.
Все этот просто синтаксический сахар для операций «реальные» монадной снизу, так что расширяется (без закомментированных частей) на что-то вроде
main = frobnicate "Hello" >>= (\x -> let y = frobnicate "Hello"
z = dothing x
in return())
В примере, конечно, не имеет никакого смысла, но, надеюсь, он иллюстрирует, где let
и <-
отличаются в пределах do
обозначение.
TL; DR: использовать <-
для присвоения имен результатам монодических операций, let
для присвоения имен всем остальным.
Хороший пример визуализировать то, что <-
делает:
do
a <- ['a'..'z']
b <- [1..3]
pure (a,b)
Вы можете попробовать это в онлайн РЕПЛ на try.frege-lang.org (Вы можете ввести это в одну строку:
do { a <- ['a'..'z']; b <- [1..3]; pure (a,b) }
- 1. В чем разница между let и let * в Scheme?
- 2. В чем разница между двумя блоками кода?
- 3. Разница между let и def
- 4. В чем разница между << и + =?
- 5. разница между блоками и контроллерами
- 6. Разница между let и var
- 7. Rails - RSpec - Разница между «let» и «let!»
- 8. В чем разница между var и let в TypScript?
- 9. В чем разница между let-bindings и ссылками в OCaml?
- 10. Vim: В чем разница между let и set?
- 11. Разница между определением и Let в Coq
- 12. В чем разница между '<>' и '! ='
- 13. В чем разница между «<>» и «! =»?
- 14. В чем разница между <и << в C?
- 15. В чем разница между и внутри R?
- 16. В чем разница между охватом блоков и охватом филиалов?
- 17. Смущает разница между let и let * в схеме
- 18. Какова разница в производительности между блоками и обратными вызовами?
- 19. В чем разница между этими двумя блоками кода?
- 20. В чем разница между следующими двумя блоками кода?
- 21. В чем разница между этими двумя блоками кода Clojure?
- 22. В ASP.Net, в чем разница между <% = и <% #
- 23. В чем разница между «<%» и «<% =» в встроенном VBScript?
- 24. В чем разница между <% # и <% = в ASP.NET MVC?
- 25. В чем разница между <% и <% i в JSP?
- 26. В чем разница между <%: и <% = в ASP.NET MVC?
- 27. В ASP.NET MVC, в чем разница между <% = и <% :?
- 28. В чем разница между этими двумя почти идентичными блоками кода?
- 29. В чем разница между этими двумя блоками кода C++?
- 30. F #: В чем разница между модулем let и типом static let?
Подробнее о что на самом деле означает 'let', и что на самом деле' <-'. И, возможно, о 'do' notaion. – lisyarus