编辑
所有您的回答都很好地解释了这一点,这只是最后一件事,任何人都可以将我指向有关类型的文档,以便我可以了解如何在内部处理类型
我正在尝试为IO实现包装类型,以了解类型。我创建了一个IO'类型,实际上是使用IO来构造的。
data IO' a = IO a
test :: String -> IO' String
test x = IO x
convert :: IO' String -> String
convert (IO x) = x
main = do
a <- getLine
return $ convert.test $ a
但是现在,如果我尝试使用IO返回IO操作,则它失败,例如,以下函数失败,给出了预期的与实际的类型错误:
fail :: IO String
fail = IO "test"
那么在Haskell中,使用相同名称的类型是否被隐藏?另外,当我调用IO时,我该如何理解是使用数据构造函数还是类型构造函数。
最后,这似乎是一个愚蠢的问题,但是我试图找到System.IO的文档,后来又找到List类型的文档,但是找不到。
答案 0 :(得分:4)
代码中没有任何内容。
在Haskell中,类型和值语言严格分开。概括地说,::
或data
/ newtype
/ type
关键字右边的所有内容(值构造函数的名称声明除外)都生活在类型级语言中,其他所有内容都使用价值级别的语言。
┌─────┐ ┌──┐ ┌─┐
data │IO' a│ = │IO│ │a│
└─────┤ └value-level└┬┘
└─type-level─────┘
┌───────────┐
fail :: │ IO String │
└──────────type-level
┌────────────────┐
fail = IO "test" │
└───────────────value-level
类型级别IO
无疑是Prelude.IO
(因为您将类型命名为IO'
),而值级别IO
无疑是{ {1}}是您自己定义的(因为IO'
不会导出任何称为Prelude.IO
或其他方式的构造函数)。
仅当您实际上对 type构造函数再次使用相同名称IO
时,隐藏才有意义:
IO
答案 1 :(得分:4)
我正在尝试为IO实现包装器类型,
您没有。在数据声明中的任何地方都没有引用IO
类型。
data IO' a = IO a
右侧的IO
不是类型IO
。它甚至都不是类型。这只是您为数据类型IO'
的值构造函数选择的名称。
如果您问ghc IO
的类型,您会得到
> :t IO
IO :: a -> IO' a
您可以为其选择其他任何名称,例如
data IO' a = C a
它只是IO'
类型的值的构造函数
答案 2 :(得分:3)
您要定义两件事:一种名为IO'
的类型和一种名为IO
的构造函数。它们都不隐藏任何内容,因为标准库既没有定义名为IO'
的类型(仅IO
),也没有定义名为IO
的构造函数(标准IO
没有任何类型)构造函数)。因此,由于构造函数和类型位于不同的名称空间中(意味着您可以拥有一个构造函数和具有相同名称的类型,而不会出现任何问题),因此不会隐藏任何内容。
因此,根据您的定义,您现在拥有类型IO
(引用Prelude.IO
)和IO'
(引用您的类型)以及构造函数IO :: a -> IO' a
。
您对fail
的定义不起作用,因为IO
构造了一个类型IO'
而不是IO
的值。您的IO
构造函数和IO
类型之间没有任何联系,因此没有理由应该起作用。