我正在使用“向您学习 haskell 教程”并已到达类型声明部分。我知道它们改变了 GHCI 给你错误消息的方式,但它们是否也影响实际功能的工作方式?如果不是,它本质上是否像在“def someFunction(x):”下面用“””“””编写的 python 函数文档? - 只是一个例子
示例代码:
removeNonUppercase :: [Char] -> [Char]
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]
编辑:我问这个是因为教程解释了 haskell 在编译时是类型推断的。
最佳答案
签名不仅仅用于文档(尽管它们对此也非常有用)。它们由编译器强制执行,这意味着通过添加签名,您可以使函数的类型比其他方式更具限制性。玩具示例:
add x y = x + y
addInt :: Int -> Int -> Int
addInt x y = x + y
*Main> :t add
add :: Num a => a -> a -> a
*Main> add 2 3
5
*Main> add 2.1 3.1
5.2
*Main> :t addInt
addInt :: Int -> Int -> Int
*Main> addInt 2 3
5
*Main> addInt 2.1 3.1 -- addInt will not accept non-Ints.
<interactive>:23:8:
No instance for (Fractional Int) arising from the literal ‘2.1’
In the first argument of ‘addInt’, namely ‘2.1’
In the expression: addInt 2.1 3.1
In an equation for ‘it’: it = addInt 2.1 3.1
除此之外,添加类型签名意味着您将在棘手的情况下得到更好(即更容易理解)的错误,因为编译器将知道您想要实现的目标,而不必自己猜测所有内容。
还有一些情况,如果没有某些签名或其他类型注释的帮助,编译器无法确定类型。也许最简单的例子是:
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.
... 它不会工作。 read
将 String
转换为 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
关于python - haskell 类型声明的使用方式是否与 python 类/函数文档相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31549024/