Как получить тип произвольного выражения в файле в Haskell?
:type
недостаточно, потому что выражение, которое я хочу, может включать локально определенные переменные, такие как вещи, назначенные с <-
, let
или where
. Набранные отверстия (замена выражения на _
и загрузка с ghc) близки, но они дают вам то, что принято там, что может быть более общим, чем выражение, которое вам интересно.
Я думал, что нашел джекпот с :type-at
, но я не могу заставить его работать, как я надеюсь. С этим файлом, названным "вещь.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 ()
. Было бы еще круче, если бы можно было выбрать между просмотром типа выражения в одиночку и типом выражения "в этой точке" (после ограничения типом, который появится с отверстием типа), но либо будет штраф.
3 ответов
когда я пытаюсь :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
.
таким образом, правой границей должна быть ячейка после окончания выражения.
иногда можно просто использовать набранное отверстие перед выражения, которое вам интересно, работает, используя отверстие, как будто это функция. Например,
return (f 3)
---->
return (_ (f 3))
таким образом, отверстие будет набрано с чем-то вроде WantedType -> OtherType
, где WantedType
тип f 3
.
это не идеально, хотя, так как отверстие предотвратит вывод типа для выполнения своей работы. То есть, иногда тип f 3
является полиморфным, и его контекстные силы его нужно создать. Например, 4 + length []
делает 4
на Int
, даже если это может быть любой Num
тип. Используя (_ 4) + length []
вводит функцию между произвольным Num
тип (который будет по умолчанию Integer
) и Int
, делая вывод типа неправильным.
вместо этого альтернативой может быть использование перевода
return (f 3)
------>
return (f 3 `asTypeOf` _)
это должно играть лучше с выводом типа и возвращать правильный тип™.
Of конечно, выяснить, как :type-at
работы должны быть лучше. Тем не менее, трюк с отверстием типа не слишком неудобен, когда у вас уже открыт редактор на месте.
Я считаю, что @chi ответ может быть улучшен (избегая проблемы вывода типа), используя фиктивный конструктор унарного типа, который не реализует Show typeclass и используя его с функцией печати:
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.
таким образом, мы можем видеть этот тип внутри манекена:либо a0 (возможно (Bool, [[Char]], Io String))