如何在Haskell中获取文件中任意表达式的类型?

时间:2018-02-07 22:14:02

标签: haskell ghc ghci

:type是不够的,因为我想要的表达式可能包含本地定义的变量,例如分配有<-letwhere的内容。输入的孔(用_替换表达式并用ghc加载)很接近,但是它们会给你那里接受的东西,这可能比你好奇的表达更为通用。

我以为我找到了:type-at的累积奖金,但是我无法让它像我希望的那样工作。使用此文件,名为“thing.hs”:

something :: ()
something = ()

main :: IO ()
main = return something

这是我在使用:type-at时得到的结果:

> :set +c
> :l thing.hs
[1 of 1] Compiling Main             ( thing.hs, interpreted )
Ok, one module loaded.
Collecting type info for 1 module(s) ... 
> :type-at thing.hs 5 8 5 13 -- "return" on last line

<no location info>: error: not an expression: ‘’
> :type-at thing.hs 5 1 5 4 -- "main" on last line
 :: IO ()
> :type-at thing.hs 5 15 5 23 -- "something" on last line

<no location info>: error: not an expression: ‘’

这与使用:type基本相同。我希望我甚至能够将return something的范围传递给Monad a => a ()IO ()。如果可以在单独查看表达式的类型和“在该点”的表达式类型(在受到类型孔出现的类型限制之后)之间进行选择,那将会更加冷却,但是否则会很好。< / p>

3 个答案:

答案 0 :(得分:6)

当我尝试:type-at thing.hs 5 8 5 14时,我得到:: () -> IO ():type-at thing.hs 5 14 5 24也有效,:type-at thing.hs 5 14 6 1也是如此。

因此,右边界应该是表达式结束后的单元格。

答案 1 :(得分:5)

有时人们可以简单地使用你对工作感到好奇的表达式的前面的,使用这个洞就像它是一个函数一样。例如

select 
  pace 
where 
  date = max(date)

通过这种方式,将使用类似return (f 3) ----> return (_ (f 3)) 的内容键入孔,其中WantedType -> OtherTypeWantedType的类型。

但这并不理想,因为这个漏洞会阻止类型推断来完成它的工作。即,有时f 3的类型是多态的,其上下文强制它被实例化。例如,f 3使4 + length []成为4,即使它可以是任何Int类型。使用Num会在任意(_ 4) + length []类型(默认为Num)和所需Integer之间引入一个函数,从而使类型推断出现异常。

相反,替代方案可以是使用翻译

Int

对于类型推断,这应该更好,并返回正确的类型。

当然,弄清return (f 3) ------> return (f 3 `asTypeOf` _) 如何运作应该会更好。当你已经在现场打开一个编辑器时,类型的漏洞技巧并不太不方便。

答案 2 :(得分:0)

我相信@chi答案可以通过使用Dummy一元类型构造函数来改进(通过避免类型推断问题),该构造函数不实现Show类型类并将其与print函数一起使用:

someExpressionWeSearchType = Right $ Just (1 , ["Foo"] , getLine)

data Dummy a = Dummy a


main = do
  putStrLn "Here we go"
  --some code here...
  let exp  = someExpressionWeSearchType
  --Debug stuff => 
  print $ Dummy exp

  -- other code here 
  putStrLn "Done"

加载时会产生以下结果:

Prelude> :l test.hs
[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:11:3: error:
    * No instance for (Show
                         (Dummy (Either a0 (Maybe (Bool, [[Char]], IO String)))))
        arising from a use of `print'
    * In a stmt of a 'do' block: print $ Dummy exp
      In the expression:
        do putStrLn "Here we go"
           let exp = someExpressionWeSearchType
           print $ Dummy exp
           putStrLn "Done"
      In an equation for `main':
          main
            = do putStrLn "Here we go"
                 let exp = ...
                 print $ Dummy exp
                 ....
   |
11 |   print $ Dummy exp
   |   ^^^^^^^^^^^^^^^^^
Failed, no modules loaded.

所以我们可以看到Dummy中的类型: a0(可能(Bool,[[Char]],IO String))