()在Haskell函数签名中是什么意思?

()在Haskell函数签名中是什么意思?,haskell,Haskell,我的Haskell文件中有以下函数: notFound :: () -> IO () notFound = putStr "Sorry, your command could not be found" 该函数不可编译。这是我得到的编译错误: todos.hs:27:12: Couldn't match expected type ‘() -> IO ()’ with actual type ‘IO ()’ Possible cause: ‘putStr’ is a

我的Haskell文件中有以下函数:

notFound :: () -> IO ()
notFound = putStr "Sorry, your command could not be found"
该函数不可编译。这是我得到的编译错误:

todos.hs:27:12:
    Couldn't match expected type ‘() -> IO ()’ with actual type ‘IO ()’
    Possible cause: ‘putStr’ is applied to too many arguments
    In the expression: putStr "Sorry, your command could not be found"
    In an equation for ‘notFound’:
        notFound = putStr "Sorry, your command could not be found"
但以下函数确实起作用:

    notFound :: IO ()
    notFound = putStr "Sorry, your command could not be found"
问题:

从我对类型签名的理解来看,它们似乎是相同的,
()
意味着没有参数被传递到函数中。不是这样吗?如果不是,那么函数签名中的
()
是什么意思?

()
是空元组。这不是什么,更像是C语言中的void类型,或者是长度为零的固定长度列表。只有一个对象的类型为:
():()
,与类似于
Bool
的对象不同

那么,为什么要这样做呢?通常,我看到它用于“关闭”类型中的一个变量。因此,
IO()
是一个
IO
操作,它总是返回相同的内容:
()


一个可能更好的例子是:
conduct A IO b
是将某个类型的
A
对象流转换为
b
对象流的东西。但是如果您有不接受输入流的东西呢?您可以将其表示为
导管()IO b
,以“关闭”输入流。(我对这里的定义很随意,但我认为它或多或少还是有效的)

您的
notFound
函数正在定义一个函数,该函数接受
()
类型的值,并返回
IO()
类型的值
()
是类型
()
的唯一值。您的函数无意中使用了无点表示法

notFound :: () -> IO ()
notFound = putStr "Sorry, your command could not be found"
相当于

notFound :: () -> IO ()
notFound () = putStr "Sorry, your command could not be found" ()
这显然不起作用,因为函数
putStrLn
不接受
()
作为第二个参数

你当然可以把它定义为

notFound :: () -> IO ()
notFound () = putStr "Sorry, your command could not be found"
这将进行编译,但相当荒谬,因为它需要作为
notFound()
调用


实际上,您需要的只是IO操作,而不是函数。因此,您可以将其定义为
notFound::IO()

嗯。。。这似乎是对我问题的一个很好的回答
()
是一种与不传递任何内容(duh!)不同的特定类型。猜一猜,我仍然不确定什么时候可以使用
notFound()
vs
notFound
来调用函数。这是一个很深的问题。看看您使用过的类型签名中包含()的所有函数可能会有所帮助。你注意到它们之间有什么共同点吗?“下面的函数[…]
notFound::IO()
”-我想这可能是你困惑的根源:你定义的不是函数。它是一个类型为
IO()
的值。函数类型为
(>)
。这完全是另一回事。哦,好吧,好吧。这是有道理的。因此,与其说是将
()
作为参数传递给函数,不如说是让函数返回
()
。对吧?对。通过执行
f()::A
,类型为
f::()->A
的函数可以轻松解析为
A
,但IO定义为始终返回某些内容,因此必须将某些内容放入插槽中。如果这还不太清楚,那么
IO a
在后台被定义为一个函数,它接受“真实世界的状态”并返回元组
(“[新]真实世界的状态”,a)
。小心使用
Void
——即
数据Void
,不使用构造函数。(虽然是的,
void
返回类型在类C语言中对应于
()
,而不是空的
void
)@antalsectt-Zabusky Great point。我本想表现出相似性,但你是对的,这可能会让人困惑。我来编辑。