我是Haskell的新手,我试图理解为什么需要编写类型声明.由于Haskell有类型推断,我什么时候需要第一行?GHCI似乎生成正确的输出我用':t'
到目前为止,我发现的唯一一个似乎需要声明的例子如下.
maximum' :: (Ord a) => [a] -> a
maximum' = foldr1 max
Run Code Online (Sandbox Code Playgroud)
但是,如果我添加"-XNoMonomorphismRestriction",则不再需要标志声明.是否存在类型推断不起作用且需要指定类型的特定情况?
由于我可能在类型声明中有错误并且没有直接的好处,我宁愿不写它.我刚刚开始学习Haskell,所以如果我错了请纠正我,因为我想养成良好的习惯.
编辑:事实证明,类型推断是真实世界Haskell书中的一个双刃剑部分,对这个主题进行了很好的讨论.
我正在学习Haskell,而Haskell Wiki上的以下表达式 让我很困惑:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么会这样.
如果我应用标准Currying逻辑,则(zipWith (+))返回一个函数将list作为参数,然后返回另一个函数,该函数将另一个列表作为参数,并返回一个list(zipWith::(a -> b -> c) -> [a] -> [b] -> [c]).因此,fibs是对列表的引用(尚未评估),并且(tail fibs)是相同(未评估)列表的尾部.当我们尝试evaluate(take 10 fibs)时,前两个元素绑定到0和1.换句话说fibs==[0,1,?,?...]和(tail fibs)==[1,?,?,?].第一次添加完成后fibs变为[0,1,0+1,?,..].同样,在第二次添加之后我们得到了[0,1,0+1,1+(0+1),?,?..]
fibs !! 4?编辑2:我刚刚发现上述问题并在此处得到了很好的解答.如果我浪费了任何人的时间,我很抱歉.
编辑:这是一个更难理解的案例(来源:Project Euler论坛):
filterAbort :: (a -> …Run Code Online (Sandbox Code Playgroud) 以下是蛮力毕达哥拉斯三胞胎问题的三个版本,附加约束为a + b + c = 1000.所有这些都符合-O3与GHC 7.0.3.下面列出了样本运行时间.
问题:
我意识到差异很小,但排序平均一致.
main=print . product . head $ [[a,b,c] | a<-[1..1000],b<-[a..1000], let c=1000-a-b, a^2+b^2==c^2]
real 0m0.046s
user 0m0.039s
sys 0m0.005s
main=print . product . head $ [[a,b,c] | a<-[1..1000],b<-[1..1000], let c=1000-a-b, a^2+b^2==c^2]
real 0m0.045s
user 0m0.036s
sys 0m0.006s
main=print . product . head $ [[a,b,c] | a<-[1..1000],b<-[1..1000], b>=a, let c=1000-a-b, a^2+b^2==c^2]
real 0m0.040s
user 0m0.033s
sys 0m0.005s
Run Code Online (Sandbox Code Playgroud) 给定空字符串时,以下两个函数的行为有所不同:
guardMatch l@(x:xs)
| x == '-' = "negative " ++ xs
| otherwise = l
patternMatch ('-':xs) = "negative " ++ xs
patternMatch l = l
Run Code Online (Sandbox Code Playgroud)
这是我的输出:
*Main> guardMatch ""
"*** Exception: matching.hs:(1,1)-(3,20): Non-exhaustive patterns in function guardMatch
*Main> patternMatch ""
""
Run Code Online (Sandbox Code Playgroud)
问题:为什么'否则'关闭空接字符串?
我试图了解类型系统在Haskell中的工作原理.
class (Show a) => MyShow a where
myShow :: a -> String
instance MyShow Integer where
myShow = show
myshow :: (Show a) => a -> String
myshow = show
main = do
putStrLn $ myshow 1
putStrLn $ myShow (2 :: Integer) -- why do I need '::Integer' here?
Run Code Online (Sandbox Code Playgroud)
为什么'myshow 1'在没有类型的情况下工作,而'myShow 2'在没有显式类型的情况下导致错误:
Ambiguous type variable `a0' in the constraints:
(MyShow a0) arising from a use of `myShow'
at nooverinst.hs:12:16-21
(Num a0) arising from the literal `2' at nooverinst.hs:12:23 …Run Code Online (Sandbox Code Playgroud)