如何在使用GHCi时为函数提供显式类型声明?

87

我该如何在 GHCi 中定义这个函数的等价函数(取自learnyouahaskell)?

import Data.List  

numUniques :: (Eq a) => [a] -> Int  
numUniques = length . nub  

如果没有类型声明,GHCi会接受函数定义,但最终得到的类型并不明确:

Prelude Data.List> import Data.List 
Prelude Data.List> let numUniques' = length . nub
Prelude Data.List> :t numUniques'
numUniques' :: [()] -> Int

生成的函数只接受单位列表作为参数。

在 GHCi 中是否有一种提供类型声明的方式?或者是否有另一种定义这些函数的方式,不需要类型声明?

我在 GHCi 指南中没有看到明显的线索,并尝试了以下类似的表达式(但均无效):

> let numUniques' = ((length . nub) :: (Eq a) => [a] -> Int)
> :t numUniques'
numUniques' :: [()] -> Int
3个回答

104

GHCi 中是否有提供类型声明的方法?

let numUniques' :: (Eq a) => [a] -> Int; numUniques' = length . nub

或者还有其他方法可以定义这样的函数而不需要类型声明吗?

如果你使用-XNoMonomorphismRestriction关闭单态化限制,就能够自动推断正确的类型。


3
我对单态性还不是很熟悉,但这个回答通常指出可以使用分号将定义分组在GHCi中 - 教程通常像在.hs文件中编写一样编写,这在尝试在GHCi中运行时会导致许多不同的问题(函数缺乏绑定等)。 - Tomasz Gandor
1
值得注意的是,自从 GHCi 7.8.1 版本以来,默认情况下启用了 -XNoMonomorphismRestriction:https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#monomorphism - N. Shead

14

GHC用户指南展示了另外两种实现这个目标的方法。 这一小节介绍了:{ ... :}结构,可以按以下方式使用:

> :{
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
| :}

或者,您可以启用多行模式

> :set +m
> let
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
| 

13
请注意,您也可以通过将“点”(即显式变量)添加回表达式来避免单态限制。 因此,这也会给出正确的类型:
```

let numUniques x = length . nub $ x

```

这被称为 eta 扩展。 - Bladt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接