我在learn you haskell读到了
枚举成员是按顺序排序的类型... 此类中的类型: (),Bool,Char ......
它也出现在一些签名中:
putChar :: Char -> IO ()
在Google中查找有关它的信息非常困难,因为答案是指“常见括号”的问题(用于函数调用,优先级问题等)。
因此,表达式()
的含义是什么?这是一种类型吗?什么是()
类型的变量?什么用于何时需要?
答案 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
的约束更少:1}:
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 () :: ()
() :: ()
它写成()
,因为它的行为非常像“空元组”。理论上有理由说明这一点,但老实说它也有很多简单的直观感。
它通常用作类型构造函数的参数,如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 ()
答案 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区分:
Void
类型); ()
类型)。命令Void
对应于前者,而不是后者。