Равный (=) символ левой стрелки (<-) в символе haskell

Рабочий код:

import System main = do [file1, file2] <- getArgs --copy file contents str <- readFile file1 writeFile file2 str 

Код сбоя:

 import System main = do [file1, file2] = getArgs str = readFile file1 writeFile file2 str 

Когда я попытался, он сделал ошибку как:

a.hs: 6: 18: ошибка синтаксического анализа на входе ‘=’

Итак, насколько отличается <- from = ?

Чтобы понять реальную разницу, вы должны понимать монады и десурагирование, описанное @rightfold в их ответе.

Для конкретного случая монады IO, как и в вашем примере getArgs , грубую, но полезную интуицию можно сделать следующим образом:

  • x <- action запускает действие IO, получает его результат и связывает его с x
  • let x = action определяет x как эквивалентное action , но ничего не запускает. Позже вы можете использовать y <- x значение y <- action .

Программисты, исходящие из императивных языков, которые допускают замыкания, могут провести это грубое параллельное сравнение с Javascript:

 var action = function() { print(3); return 5; } // roughly equivalent to x <- action print('test 1') var x = action() // output:3 // x is 5 // roughly equivalent to let y = action print('test 2') var y = action // output: nothing // y is a function // roughly equivalent to z <- y print('test 3') var z = y() // output:3 // z is 5 

Опять же: это сравнение сосредоточено только на IO. Для других монадов вам нужно проверить, что >>= самом деле, и подумать о том, что нужно do .

 do x <- y fx 

эквивалентно:

 y >>= \x -> fx 

 do let x = y fx 

эквивалентно

 fy 

т. е. let / = не имеет монадического связывания, а <- делает.

Код не компилируется, потому что типы не совпадают. Давайте загрузим сеанс GHCI и рассмотрим типы используемых вами функций –

 > :t writeFile writeFile :: FilePath -> String -> IO () > > :t readFile readFile :: FilePath -> IO String 

Поэтому writeFile хочет FilePath и String . Вы хотите получить String из readFile но readFile возвращает IO String вместо String .

Хаскелл – очень принципиальный язык. Он имеет различие между чистыми функциями (которые дают одинаковые выходы каждый раз, когда они вызываются с теми же аргументами) и нечистым кодом (который может давать разные результаты, например, если функция зависит от некоторого ввода пользователя). Функции, имеющие отношение к вводу / выводу (IO), всегда имеют тип возврата, который помечен знаком IO . Система типов гарантирует, что вы не можете использовать нечистый код IO внутри чистых функций – например, вместо того, чтобы возвращать String функция readFile возвращает IO String .

Здесь важна <- обозначение. Это позволяет вам получить String внутри IO и гарантирует, что независимо от того, что вы делаете с этой строкой, функция, которую вы определяете, всегда будет отмечена знаком IO . Сравните следующее:

 > let x = readFile "tmp.txt" > :tx x :: IO String 

который не является тем, что мы хотим, к этому

 > y <- readFile "tmp.txt" > :ty y :: String 

это то, что мы хотим. Если у вас есть функция, которая возвращает IO a и вы хотите получить доступ к a , вам нужно использовать <- для присвоения результата имени. Если ваша функция не возвращает IO a , или если вы не хотите попасть в a внутри IO вы можете просто использовать = .

 let x = readFile file1 

Это принимает действие « readFile file1 » и сохраняет действие в x .

 x <- readFile file1 

Это выполняет действие « readFile file1 » и сохраняет результат действия в x .

В первом примере x - это объект недействительного объекта ввода-вывода. Во втором примере x - это содержимое файла на диске.

  • Что означает () в Haskell
  • Каковы некоторые убедительные варианты использования зависимых типов методов?
  • Как определить применение Lisp в Haskell?
  • Состав составной функции: Как работает (.). (.)?
  • Как определить функцию в ghci через несколько строк?
  • В Haskell, когда мы используем это с let?
  • Список различных типов?
  • Почему ленивая оценка полезна?
  • Почему Хаскелл (иногда) называют «Лучшим императивным языком»?
  • Объясните этот fragment кода Хеккеля, который выводит stream простых чисел
  • Haskell GHC: какова временная сложность совпадения шаблона с конструкторами N?
  • Давайте будем гением компьютера.