2013-12-04 1 views
18

я прочитал в learn you haskell, чтоЧто скобки() используются сами по себе?

члены

Enum последовательно упорядоченный типы ... Типы в этом классе: (), Bool, Char ...

Также появляется в некоторых подписи:

putChar :: Char -> IO() 

Очень сложно найти информацию об этом в Google, поскольку ответы касаются проблем «общего паре» ntheses "(использование в вызовах функций, проблемах с приоритетом и т. п.).

Таким образом, что означает выражение ()? Это тип? Что такое переменные типа ()? Что используется для и когда это необходимо?

+2

В общем, чтобы ответить на вопрос «есть« X »тип», введите ': k X' в ghci, чтобы попытаться определить его вид. Если 'X' является типом, вы получите что-то вроде' X :: * ', считаете, что« 'X» имеет вид _type_ ». В противном случае будет поднята ошибка. – phg

ответ

21

Это как тип, так и значение. () - это особый тип «произносится» единица, и он имеет одно значение: (), также ярко выраженный блок. Он по существу такой же, как тип void в Java или C/C++. Если вы знакомы с Python, подумайте об этом как о NoneType, который имеет singleton None.

Полезно, если вы хотите обозначить действие, которое ничего не возвращает. Это чаще всего используется в контексте Монад, например, монады IO. Например, если вы имели следующую функцию:

getVal :: IO Int 
getVal = do 
    putStrLn "Enter an integer value:" 
    n <- getLine 
    return $ read n 

И по какой-то причине вы решили, что вы просто хотели раздражать пользователя и выбросить номер они только что прошли в:

getValAnnoy :: IO() 
getValAnnoy = do 
    _ <- getVal 
    return() -- Returns nothing 

Однако, return просто Monad функция, так что мы могли бы абстрактным это немного дальше

throwAwayResult :: Monad m => m a -> m() 
throwAwayResult action = do 
    _ <- action 
    return() 

Тогда

getValAnnoy = throwAwayResult getVal 

Однако, вы не должны писать эту функцию самостоятельно, она уже существует в Control.Monad как функции void, которая является еще менее ограничительным и работает на Functor с:

void :: Functor f => f a -> f() 
void fa = fmap (const()) fa 

Почему это работает на Functor вместо Monad? Ну, для каждого Monad Например, вы можете написать Functor экземпляр как

instance Monad m => Functor m where 
    fmap f m = m >>= return . f 

Но вы не можете сделать Monad из каждого Functor. Это как квадрат прямоугольника, но прямоугольник не всегда квадрат, Monads образуют подмножество функторов.

+0

Спасибо. И тогда, что это значит 'IO()'? – cibercitizen1

+1

Это означает monad 'IO', который может содержать только одну вещь -'() 'типа'() '. – andrybak

+1

@ cibercitizen1 'IO' - это конструктор типа, он принимает тип и дает другое (например,' [] ', которое принимает любой тип и делает« списки »этого). 'IO()' - это конструктор типа 'IO', применяемый к(), чтобы указать, sort, что' putChar' не возвращает монадическое значение (так как оно всегда возвращает то же самое). – Guido

6

Это как тип, так и значение.

Это unit type, тип, который имеет только одно значение. В Haskell его имя и только значение выглядят как пустой кортеж: ().

8

Как говорили другие, это тип единицы, который имеет одно значение, называемое единицей. В синтаксисе Haskell это легко, если путать, выражается как () ::(). Мы тоже можем сделать свой собственный.

data Unit = Unit 

>>> :t Unit :: Unit 
Unit :: Unit 
>>> :t() ::() 
() ::() 

Это написано в (), потому что он ведет себя очень похоже на «пустой кортеж» будет. Есть теоретические причины, почему это имеет место, но, честно говоря, это делает много простого интуитивного чувства.

Он часто используется в качестве аргумента для конструктора типа, такого как IO или ST, когда его контекст интересующего значения, а не самого значения. Это интуитивно верно, потому что, если я скажу вам, что у меня есть значение типа (), вам больше ничего не нужно знать --- есть только один из них!

putStrLn :: String -> IO()  -- the return type is unimportant, 
           -- we just want the *effect* 

map (const()) :: [a] -> [()] -- this destroys all information about a list 
           -- keeping only the *length* 

>>> [(),(),() ] :: [()]  -- this might as well just be the number `3` 
           -- there is nothing else interesting about it 

forward :: [()] -> Int   -- we have a pair of isomorphisms even 
forward = length 

backward :: Int -> [()] 
backward n = replicate n() 
4

Как уже говорили другие, () в Haskell является как название типа «единицы», и единственное значение указанного типа.

Одна из запутывающих вещей в переходе от императивного программирования к Haskell заключается в том, что способ, которым языки имеют дело с понятием «ничего», отличается. Более запутанным является словарь, потому что императивные языки и Haskell используют термин «пустота» для обозначения диаметрально разных вещей.

В императивном языке, «функция» (которая не может быть истинной математической функции) может быть «пустота» в качестве типа возвращаемого значения, так как в этом псевдокода, например:

void sayHello() { 
    printLn("Hello!"); 
} 

В этом случае, void означает, что «функция», если она вернется, не приведет к результату результата. (Другая возможность заключается в том, что они не могут возвращаться, они могут зацикливаться навсегда или с ошибкой или исключением.)

В Haskell, однако, все функции (и действия IO) должны приводить к результату. Поэтому, когда мы пишем IO действие, которое не производит каких-либо интересное возвращаемое значение, мы делаем его вернуть ():

sayHello :: IO() 
sayHello = putStrLn "Hello!" 

Дальнейшие действия будут просто игнорировать значение () результата.

Теперь вам, вероятно, не нужно слишком беспокоиться об этом, но есть одно место, где это запутывает, а это то, что in Haskell there is a type called Void, но это означает нечто совершенно отличное от императивного программирования void. Из-за этого слово «пустота» становится минным полем при сравнении Haskell и императивных языков, потому что значение полностью отличается при переключении парадигм.

В Haskell Void - это тип, который не имеет любых значений. Самым большим следствием этого является то, что в Haskell функция с возвращаемым типом Void никогда не может вернуться, она может только сбой или ошибка навсегда. Зачем? Потому что функция должна была бы получить значение типа Void для возврата, но такого значения нет.

Это, однако, не актуально, пока вы не работаете с более продвинутыми методами, поэтому вам не нужно беспокоиться об этом, кроме как остерегаться слова «пустота»."

Но больше урок заключается в том, что необходимо и понятия Haskell„нет возвращаемого значения“отличаются Haskell различает:.

  1. Вещи, которые могут возвращение, но результат которого не будет иметь никакого информацию (() тип);.
  2. Вещи, которые не могут возврата, независимо от того, что (Void типа)

Обязательный void соответствует первому, а не последнему.

+0

Это меня смущает. Я бы сказал, что императивный «void» по-прежнему соответствует последнему понятию, просто императивные функции всегда «завернуты в« IO ». Совершенно разумно писать 'putStrLn :: String -> IO Void', просто не разумно пытаться что-либо сделать с« значением ». –

+1

@ J.Abrahamson: 'printf' по-прежнему является функцией первого типа. Лучшим примером Void в императивной настройке будет функция 'exit' или оператор' assert'. – hugomg

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

  • Нет связанных вопросов^_^