括号()使用的是什么意思?

时间:2013-12-04 16:19:02

标签: haskell parentheses

我在learn you haskell读到了

  

枚举成员是按顺序排序的类型... 此类中的类型:   (),Bool,Char ......

它也出现在一些签名中:

putChar  ::    Char -> IO ()

在Google中查找有关它的信息非常困难,因为答案是指“常见括号”的问题(用于函数调用,优先级问题等)。

因此,表达式()的含义是什么?这是一种类型吗?什么是()类型的变量?什么用于何时需要?

4 个答案:

答案 0 :(得分:23)

它既是一种类型,也是一种价值。 ()是一种特殊类型“发音”单位,它有一个值:(),也是发音单位。它与Java或C / C ++中的类型void基本相同。如果您熟悉Python,请将其视为具有单NoneType的{​​{1}}。

当您想要表示不返回任何内容的操作时,它非常有用。它最常用于Monads的上下文中,例如None monad。例如,如果您具有以下功能:

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。这就像一个正方形是一个矩形,但一个矩形并不总是一个正方形,Monads形成一个Functors的子集。

答案 1 :(得分:9)

正如其他人所说,它是具有一个称为单位的值的单位类型。在Haskell语法中,如果容易混淆,很容易表达为() :: ()。我们也可以很容易地制作自己的。

data Unit = Unit

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

它写成(),因为它的行为非常像“空元组”。理论上有理由说明这一点,但老实说它也有很多简单的直观感。

它通常用作类型构造函数的参数,如IOST,当它的值是有趣的值的上下文时,而不是值本身。这是直观的,因为如果我告诉你我有()类型的值,那么你不需要知道更多 - 只有其中一个!

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 ()

答案 2 :(得分:6)

它既是一种类型,也是一种价值。

它是unit type,只有一个值的类型。在Haskell中,它的名称和唯一值看起来像空元组:()

答案 3 :(得分:4)

正如其他人所说,Haskell中的()都是&#34;单位的名称&#34;类型,以及所述类型的唯一值。

从命令式编程转向Haskell的一个令人困惑的事情是,语言处理的概念是什么&#34;没有&#34;是不同的。更令人困惑的是词汇量,因为命令式语言和Haskell使用术语&#34; void&#34;意思是完全不同的东西。

用命令式语言,&#34;功能&#34; (这可能不是一个真正的数学函数)可能有&#34; void&#34;作为其返回类型,如在此伪代码示例中:

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

在这种情况下,void表示&#34;功能,&#34;如果它返回,将不会产生结果值。 (另一种可能性是它们的功能可能不会返回 - 它可能会永远循环,或者因错误或异常而失败。)

然而,在Haskell中,所有函数(和IO动作)必须产生结果。因此,当我们编写一个IO操作并没有产生任何有趣的返回值时,我们会返回()

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

稍后的操作将忽略()结果值。

现在,您可能不需要过多担心这一点,但有一个地方让人感到困惑,那就是in Haskell there is a type called Void,但这意味着与命令式编程完全不同{ {1}}。因此,“&#34; void&#34;在比较Haskell和命令式语言时会成为一个雷区,因为当你切换范式时,意思是完全不同。

在Haskell中,void是一种没有任何值的类型。这样做的最大结果是,在Haskell中,返回类型为Void的函数永远不会返回,它只会因错误或循环失败而失败。为什么?因为函数会产生Void类型的值以便返回,但是没有这样的值。

然而,在您使用某些更先进的技术之前,这是不相关的,因此除了要小心“#34; void”之外,您不必担心它。&#34;

但更重要的教训是,命令式和Haskell的概念没有回报价值&#34;是不同的。 Haskell区分:

  1. 可能返回的内容但其结果不会有任何信息(Void类型);
  2. 无法返回的内容,无论是什么(()类型)。
  3. 命令Void对应于前者,而不是后者。