Istnieje wiele sposobów na zrobienie tego, koncepcyjnie. Niestety, większość z nich nie działa. Niestety!
Po pierwsze, jako programista funkcjonalnej, Założę się, że to jest to, czego naprawdęchcesz napisać:
instance Listable (\a -> (a, a)) where
asList (p, q) = [p,q]
Niestety wpisać szczebla lambdas nie istnieją. Moglibyśmy napisać o nazwie wersję powyższej lambda przy użyciu typu synonim:
type Same2 f a = f a a
instance Listable (Same2 (,)) where { ... }
Że nie wolno albo, ponieważ typ synonimem nie jest w pełni stosowane. Mogliśmy zamiast wyobrazić klasę typu biorąc dodatkowy argument, który opisuje, jak zastosować zmienne typ:
class Listable app f where
asList :: app f a -> [a]
instance Listable __ Maybe where { ... }
instance Listable __ (,) where { ... }
nawet bez myślenia o tym, co app
może być, to również nie dlatego, że nie mają spójnego rzeczowe dla parametr f
.
Przechodząc do rzeczy, które rzeczywiście działają, myślę, że najbardziej popularnym sposobem jest zawarcie podejścia synonimów typu wewnątrz newtype
, a następnie poradzenie sobie z zawijaniem i rozpakowywaniem, które obejmuje.
newtype Same2 f a = Same2 (f a a)
instance Listable (Same2 (,)) where { ... }
Jest funkcjonalny, jeśli nieco brzydki. Możesz również w ten sposób zdefiniować kompozycję konstruktora typu i inne zabawki, a następnie odejść z pozbawionymi punktów tekstem typami ukrytymi pod stosem skoczni.
W końcowym podejściu, można również zakodować podejście powyżej lambda w stylu „w odwrotnym kierunku”, przechodząc z wersja w pełni stosowane, do parametr pojedynczy typ:
class Listable t where
type ListableElem t :: *
asList :: t -> [ListableElem t]
Being umiejętność robienia tego typu rzeczy jest jedną z głównych motywacji rodzin typów. To samo można wyrazić za pomocą MPTC i fundeps, ale jest to 1) równoważne i 2) o wiele brzydsze, więc nie będę się tym przejmował.
Przepraszamy za bycie leniwym, aby go wypróbować, ale ostatnie podejście pozwoliłoby na "Listable (a, a)" - czyż nie? – yatima2975
@ yatima2975: Kosztem posiadania różnych instancji z '(,)' jako najbardziej zewnętrznym konstruktorem typów, tak. Prawdopodobnie powinienem podać to jako przykład w mojej odpowiedzi, teraz, gdy o tym wspomniałeś ... –