2012-10-03 13 views
7

mam jakiś rodzaj contrived:polimorficzne ograniczenie

{-# LANGUAGE DeriveFunctor #-} 

data T a = T a deriving (Functor) 

... i tego typu jest wystąpienie pewnej klasie contrived:

class C t where 
    toInt :: t -> Int 

instance C (T a) where 
    toInt _ = 0 

Jak mogę wyrazić ograniczenie funkcji, która jest T a instancja jakiejś klasy dla wszystkich a?

Na przykład rozważmy następującą funkcję:

f t = toInt $ fmap Left t 

Intuicyjnie spodziewałbym wyżej funkcja działała od toInt prac nad T a dla wszystkich a, ale nie mogę wyrazić, że w tego typu. To nie działa:

f :: (Functor t, C (t a)) => t a -> Int 

... bo gdy stosujemy fmap typ stał Either a b. Nie mogę rozwiązać ten problem przy użyciu:

f :: (Functor t, C (t (Either a b))) => t a -> Int 

... bo b nie reprezentuje zmienną powszechnie ilościowo. Nie mogę powiedzieć:

f :: (Functor t, C (t x)) => t a -> Int 

... lub użyj forall x się sugerować, że ograniczenie jest ważne we wszystkich x.

Moje pytanie brzmi, czy istnieje sposób, aby powiedzieć, że ograniczenie jest polimorficzne w stosunku do niektórych zmiennych tego typu.

+0

Zakładam, że coś takiego jak 'klasa C T gdzie toInt :: TA -> Int' nie będzie działać i trzeba' C' się być rodzaju '* -> Więzienie "? Czy pomocny jest tutaj polimorfizm? –

+0

@ C.A.McCann Konstruktor typu betonu, który mam na myśli to 'Proxy' z' pipes', a konkretną klasą jest 'Monad'. Używam funkcji użytkowych klasy typów dla typów proxy, dlatego istnieje ograniczenie. Podążając za twoją sugestią, zdefiniowałbym wtedy klasę 'MonadP' wyspecjalizowaną w kształcie konstruktora typu" Proxy "i użyłaby tego jako ograniczenia. Wadą jest to, że jeśli użytkownicy chcieli pisać funkcje użyteczności proxy w języku polimorficznym w typie proxy, musieliby ponownie powiązać notację, aby zamiast tego używać 'MonadP'. –

+2

Nie można tego zrobić bezpośrednio, ale można symulować, tak jak w odpowiedzi Romana. Oto odpowiedni bilet GHC: http://hackage.haskell.org/trac/ghc/ticket/2893 – glaebhoerl

Odpowiedz

6

Korzystanie pakiet constraints:

{-# LANGUAGE FlexibleContexts, ConstraintKinds, DeriveFunctor, TypeOperators #-} 

import Data.Constraint 
import Data.Constraint.Forall 

data T a = T a deriving (Functor) 

class C t where 
    toInt :: t -> Int 

instance C (T a) where 
    toInt _ = 0 

f :: ForallF C T => T a -> Int 
f t = (toInt $ fmap Left t) \\ (instF :: ForallF C T :- C (T (Either a b))) 
+3

Warto również przyjrzeć się źródłu tego 'ForallF', choćby po to, aby podziwiać, jak proste/brzydkie/przerażające są idee to jest :) – copumpkin

+0

@copumpkin: Właściwie to mam pytanie - http://stackoverflow.com/questions/12728159/how-does-the-constraints-package-work –

Powiązane problemy