2014-12-06 5 views
6

Я иногда сталкивался с этой проблемой и, наконец, хотел спросить, существует ли общее решение или шаблон. Возможно ли сделать переменную типа во вложенном контексте ссылкой типа из внешнего контекста? Например,Haskell Ссылка на переменную типа

foo :: a -> ... -> .. 
foo = ... 
    where bar :: a -> ... 

Теперь bar «s a отличается от Foo-х a. Обычно это то, что я хочу, но иногда это затрудняет жизнь, и мне нужно сделать их одинаковыми. Я использовал грязные трюки, чтобы заставить средство проверки типов объединить два в прошлом, но иногда их прерывают. Вот мой последний пример (функция Parsec), который побудил меня наконец задать этот вопрос.

data Project = ... deriving Enum 
data Stuff = ... 

pProject :: Monad m => P m Stuff 
pProject = do 
    stuff <- pStuff 
    ... 
    convert stuff <$> pEnum :: P m Project 

pEnum :: (Monad m, Enum a) => String -> P m a 
pEnum = ... 

convert функция нужен тип, поэтому я должен был указать аннотацию :: P m Project. Однако это означает, что я должен также ввести m, что, к сожалению, не совпадает с m, как в сигнатуре функции. Отчеты шашки типа это с:

Не удался вывести Monad m1 вытекающие из использования pEnum из контекста Monad m

Есть ли способ, чтобы ссылаться на подписи функции-х m без какого-либо уродливых взломать? (Безобразная хак будет вставить фиктивный код, который не получает выполняется, но существует только для объединения двух типов.)

ответ

13

Вы ищете ScopedTypeVariables расширения, который позволяет ссылаться на переменные типа из содержащих областей.

{-# LANGUAGE ScopedTypeVariables #-} 

Для обеспечения обратной совместимости, это относится только к типу подписи, которые имеют явную forall. Таким образом, вы должны написать:

pProject :: forall m. Monad m => P m Stuff 

После этого, вы бы иметь возможность ссылаться на правильный тип переменной m внутри сферы pProject.

+5

Благодарим за указание, что 'ScopedTypeVariables' применяется только к сигнатурам с явным' forall'. Неудивительно, что это почти никогда не работало ... – Cirdec

+3

Это не совсем так - 'ScopedTypeVariables' делает переменные типа, охваченные объявлениями класса даже без' forall'. Таким образом, он может изменить смысл надуманной программы Haskell 2010. – shachaf

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