如果在不同模块中使用了相同的名称,haskell是否会隐藏类型?

时间:2018-12-04 12:06:42

标签: haskell

编辑

所有您的回答都很好地解释了这一点,这只是最后一件事,任何人都可以将我指向有关类型的文档,以便我可以了解如何在内部处理类型

我正在尝试为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类型的文档,但是找不到。

3 个答案:

答案 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类型之间没有任何联系,因此没有理由应该起作用。