haskell类型声明与python类/函数文档的使用方式相同吗?

2024-05-21 00:20:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用“向您学习haskell教程”,并且已经到达了类型声明部分。我知道它们改变了GHCI给出错误消息的方式,但它们是否也会影响实际函数的工作方式?如果不是,它是否本质上像是在defsomefunction(x):”下面用“”“”编写的python函数文档?-只是个例子

示例代码:

removeNonUppercase :: [Char] -> [Char]  
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]

编辑:我这么问是因为教程解释了haskell是在编译时推断的类型。在


Tags: 函数文档声明消息类型haskell错误方式
3条回答

类型声明是程序员用来检查代码是否正常的工具。Haskell所做的类型推断永远是正确的,但它可能不是您在编写代码时所期望的那样。您可能希望得到Int->;Int->;Int类型的函数,但代码可能会告诉推理算法该函数是(Int,Int)->;Int类型,因为您在某个地方忘了一个括号。在

它们还可以作为程序员的一种文档形式。有时在编写代码时查看函数的类型是非常有帮助的。通常(如果函数的名称是好的),您可以通过查看函数的名称和类型来确定它应该做什么。文档仍然非常有用,但是当您开始编写和阅读更多的函数式程序时,类型就变成了帮助您理解代码的东西。在

在简单的情况下,类型声明与Haskell推断的类型完全相同,只是documentation+有助于避免令人困惑的错误。但也有例外:

(1)您可以给出一个比推断的类型声明更受限制的类型声明。E、 g

squareInt :: Int -> Int
squareInt x = x*x

如果没有声明,它将被推断为Num t => t -> t。 但有了它,该函数只能用于Ints,而不能用于任何数值类型。这有时对于将函数限制在预期的用例中,或防止类型歧义错误非常有用。在

(2)许多语言扩展需要类型声明,因为它们超出了推理算法支持的类型系统的一部分。例如,rank n类型:

^{pr2}$

这还包括标准的Haskell特性“多态递归”(polymorphic recursion),这意味着使用与最初调用时不同的类型递归调用函数。在

签名不仅仅用于文档(尽管它们对文档也非常有用)。它们是由编译器强制执行的,这意味着通过添加签名,可以使函数的类型比其他类型更具限制性。玩具示例: 在

add x y = x + y

addInt :: Int -> Int -> Int
addInt x y = x + y
^{pr2}$

除此之外,添加类型签名意味着您将在复杂的情况下得到更好(即更容易理解)的错误,因为编译器将知道您想要实现什么,而不必自己猜测所有的东西。在

还有一些情况下,如果没有一些签名或其他类型注释的帮助,编译器无法确定类型。也许最简单的例子是:

readAndShow s = show (read s)

如果您尝试在不指定任何类型的情况下使用它。。。在

Foo.hs:6:17:
    No instance for (Show a0) arising from a use of ‘show’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance (GHC.Arr.Ix a, Show a, Show b) => Show (GHC.Arr.Array a b)
          Defined in ‘GHC.Arr’
      instance Show a => Show (Maybe a)   Defined in ‘GHC.Show’
      instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
          Defined in ‘GHC.Real’
      ...plus 26 others
    In the expression: show (read s)
    In an equation for ‘readAndShow’: readAndShow s = show (read s)

Foo.hs:6:23:
    No instance for (Read a0) arising from a use of ‘read’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance (GHC.Arr.Ix a, Read a, Read b) => Read (GHC.Arr.Array a b)
          Defined in ‘GHC.Read’
      instance Read a => Read (Maybe a)   Defined in ‘GHC.Read’
      instance (Integral a, Read a) => Read (GHC.Real.Ratio a)
          Defined in ‘GHC.Read’
      ...plus 25 others
    In the first argument of ‘show’, namely ‘(read s)’
    In the expression: show (read s)
    In an equation for ‘readAndShow’: readAndShow s = show (read s)
Failed, modules loaded: none.

。。。这行不通。readString转换为some类型,show则相反。但是,如果没有指定read s的类型,编译器就无法判断您要将String读为哪种类型。所以你要么需要指定中间类型。。。在

readAndShowAsInt s = show (read s :: Int)
*Main> readAndShowAsInt "2"
"2"

。。。或者让别人帮你选一个类型:

readAndAdd :: String -> Int -> Int
readAndAdd s y = read s + y
*Main> readAndAdd "2" 3
5

相关问题 更多 >