我有以下
readStatement :: String -> IO [Transaction]
readStatement path = do
csvData <- readFile path
return $ catMaybes (map _ (splitOn "\r" csvData))
GHC为洞[Char] -> Maybe Transaction
找到以下类型。
现在,如果我给这个洞命名并进入where子句
readStatement :: String -> IO [Transaction]
readStatement path = do
csvData <- readFile path
return $ catMaybes (map process (splitOn "\r" csvData))
where process = _
GHC找不到新行的类型,但给出:
Found hole ‘_’ with type: t
Where: ‘t’ is a rigid type variable bound by
the inferred type of process :: t at Statement.hs:63:11
Relevant bindings include
process :: t (bound at Statement.hs:63:11)
path :: String (bound at Statement.hs:60:15)
readStatement :: String -> IO [Transaction]
(bound at Statement.hs:60:1)
In the expression: _
In an equation for ‘process’: process = _
In an equation for ‘readStatement’:
readStatement path
= do { csvData <- readFile path;
return $ catMaybes (map process (splitOn "\r" csvData)) }
where
process = _
代码是完全等价的,那么类型推断怎么会给出相同的结果呢? (我正在使用GHC 7.8.3)
答案 0 :(得分:4)
在以下代码中
let x = something
in f x
x = something
的类型推断不考虑f
。也就是说,推断出something
的类型,推广到多态类型,x
获得该类型。这可能会为x
分配一个比f
所需类型更通用的类型。
更具体地说,在
中let x = \y->y
in x "hello"
我们推断出多态绑定x :: forall a. a->a
。
请注意,String
尚未显示。
我猜GHC就是在let
定义上执行类型推断之后打印出类型的孔信息。在已发布的示例中,
do one
two
where process = _
我们推断_ :: t
而不查看上下文并打印该类型。如果您想要更专业(单态)类型,请尝试改为
(\process -> do
one
two
) _
上面,我们不使用let
或where
,因此只会推断出单态类型。