2013-02-24 2 views
2

Мы все знаем, что :t в ghci дает тип выражения:преобразовать выражение в строку, описывающую его тип в скрипте haskell?

Prelude> :t [1..] 
[1..] :: (Enum t, Num t) => [t] 

Что мне нужно, это эквивалент :t в Haskell скрипта (я буду называть его typeStr):

main = putStrLn $ typeStr [1..] 

который может напечатать что-то вроде (Enum t, Num t) => [t] на экране.

Возможно ли это?

+4

Зачем вам это нужно? Какова ваша основная проблема? – dave4420

+0

Просто проявляйте интерес к тому, как это сделать, я хотел бы написать вспомогательную функцию, которая может дать результат выражения, а также его тип. – Javran

+1

Если вы хотите использовать эту функцию только в ghci, вы должны запустить ': set + t' в приглашении ghci: впоследствии он расскажет вам типы выражений, которые вы вводите, когда обычно они будут сообщать вам только их значения. – dave4420

ответ

5

Да, есть несколько способов.

1. Используйте динамический ввод

Для простого случая мономорфных типов, вы можете использовать печатаемый экземпляр:

Data.Dynamic> typeOf [1..] 
[Integer] 

2. Используйте оценку выполнения

Однако, чтобы сделать это правильно - чтобы получить тип полиморфных значений - вам понадобится полный контроль типа GHC. Например. с помощью библиотеки GHC-апи, и его красивой обертке, hint:

Language.Haskell.Interpreter> runInterpreter $ typeOf "[1..]" 
Right "(P.Enum t, P.Num t) => [t]" 

Какой правильно выведенный тип с использованием полного GHC проверки типов, вызывается динамически.

1

Короткий ответ: Нет

Haskell обычно не позволяет записывать выражения, которые Тип неизвестно до выполнения, так что никогда не бывает необходимо для выполнения поиска типа в первую очередь.

Сказав это, : способы динамической типизации и, возможно, поддержка печати сигнатур типа ... но это, вероятно, совсем не то, что вы хотите делать вообще.

Другой возможностью является использование шаблона Haskell для поиска сигнатуры типа во время компиляции. Я не знаю, если кто-то уже написал код, который еще ...

3

Да, вы можете, если тип является экземпляром Data.Typeable:

import Data.Typeable 
typeStr :: Typeable a => a -> String 
typeStr a = show $ typeOf a 

Я не думаю, вы, однако, получите наиболее общий тип, поскольку аргумент будет иметь определенный тип. Например, typeStr [1..] дает [Integer] в ghci.