2014-12-06 20 views
6

Od czasu do czasu wpadam na ten problem i na koniec chciałem zapytać, czy istnieje wspólne rozwiązanie lub wzorzec. Czy można utworzyć zmienną typu w zagnieżdżonym kontekście, odwołując się do typu z zewnętrznego kontekstu? Na przykładHaskell Odwoływanie się do zmiennej typu

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

Teraz bar „s a jest inna niż Foo a. Zazwyczaj to jest to, czego chcę, ale czasami sprawia, że ​​życie jest trudne, i muszę sprawić, aby były takie same. Użyłem brudnych sztuczek, aby zmusić kontroler do zunifikowania tych dwóch w przeszłości, ale czasami udaremnia się. Oto mój najnowszy przykład (funkcja Parsec), który zachęcił mnie do zadania tego pytania.

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 = ... 

Funkcja convert potrzebne typ, dlatego musiałem określić adnotacji :: P m Project. Oznacza to jednak, że muszę również wprowadzić m, który nie jest niestety taki sam, jak m jak w sygnaturze funkcji. Do typu raporty Checker to z:

Nie można wywnioskować Monad m1 wynikające ze stosowania pEnum z kontekstu Monad m

Czy istnieje sposób, aby odwoływać funkcja podpis na m bez jakiegoś brzydkiego włamania? (Brzydka Hack byłoby wstawienie kodu manekin, który nie zostanie wykonany, ale istnieje tylko w celu ujednolicenia tych dwóch rodzajów).

Odpowiedz

13

Szukacie, rozszerzenie ScopedTypeVariables który pozwala odwołać się zmienne typu z zawierającymi zakresów.

{-# LANGUAGE ScopedTypeVariables #-} 

Dla kompatybilności wstecznej, to odnosi się tylko do wpisywania podpisów, które mają wyraźny forall. Więc trzeba by napisać:

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

Po tym, byłbyś w stanie odnieść się do odpowiedniego typu zmiennej m wewnątrz zakresu pProject.

+5

Dzięki za wskazanie, że 'ScopedTypeVariables' dotyczy tylko sygnatur z jawnym' forall'. Nic dziwnego, że wydawało się, że prawie nigdy nie działało ... – Cirdec

+3

To nie do końca prawda - 'ScopedTypeVariables' powoduje, że zmienne typu są określane w deklaracjach klas nawet bez' forall'. Może więc zmienić znaczenie wymyślonego programu Haskell 2010. – shachaf