2012-03-06 3 views
4

Рассмотрим этот код:Почему этот шаблон Haskell работает?

 
magic :: String -> Q Exp 
magic s = [e| putStrLn s |] 

Теперь, как лучше, как я могу сказать, что это не должно реально работать. Внутри кронштейнов Оксфорда s не входит в объем. И все же, все это, видимо, прекрасно работает.

Если немного изменить этот пример, теперь он ломает ужасно:

 
magic :: Exp -> Q Exp 
magic (VarE n) = [e| putStrLn (nameBase n) |] 

Так же, как и раньше, мы имеем переменную не входят в комплект. И это время, он ломается. Но он не жалуется на переменную, которая не входит в сферу охвата; вместо этого он скулит о каком-то недокументированном классе, лишенном экземпляра.

Кто-нибудь знает, что происходит?

+0

Как вы управляете монадами Q? Обычно вещи выполняются во время компиляции, но некоторые из них работают в режиме исполнения, а вещи более хрупкие. –

ответ

12

sявляется в области внутри кронштейнов Оксфорда. В принципе, вам разрешено использовать значения нескольких типов - те, у которых есть Lift экземпляры - внутри цитируемого выражения, и они автоматически превратятся в соответствующий код, чтобы воссоздать соответствующее значение на другом конце.

Например, Lift instance for Integers просто создает соответствующий целочисленный литерал, а instance for Maybe просто создает соответствующие конструкторские приложения. Вы даже можете определить свои собственные экземпляры Lift.

Вы получаете ошибку «нет экземпляра», потому что n - это Name, что не является Lift.

2

Я думаю, что короткий ответ заключается в том, что ожидается, что волшебная функция будет работать, поскольку скобки цитаты действительно фиксируют свои локальные переменные (в некотором смысле). По существу, локальные переменные времени компиляции в квадратных скобках заменяются своими буквальными значениями и становятся константами времени выполнения. Это достигается путем негласного вызова функции лифта, так что [| .. вар .. |] становится [| $ (lift var) |].

Возможно, вы смешиваете это поведение с тем фактом, что они фиксируют локальные переменные однозначно, так что повторные вызовы одной и той же цитаты не будут мешать именам переменных друг друга. Это достигается за счет вызовов newName за кулисами, что обеспечивает уникальные имена переменных.

Если это помогает, я лично думаю о скобках цитат как «генераторы сращивания» - небольшие фрагменты кода Haskell, которые будут преобразованы в AST во время компиляции и, следовательно, станут сплайсами, готовыми к включению везде. Как указано в уроках Булата (links from), они действуют как форма макропрепроцессора, так как они представляют собой смеси функций Haskell, генерирующих код, и простое автоматическое преобразование кода Хеккеля в TH AST.

Редактировать: Кажется, что я побил меня до ответа - я оставляю свой ответ, если он дает дополнительную ценность.

Смежные вопросы