Pregunta Instancias de sinónimos de tipo multiparámetro


Estoy tratando de averiguar si es posible (y cómo) definir instancias de clase para sinónimos de tipo multiparámetro.

Por ejemplo:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

type F a b = a -> b
data DF a b = DF (a -> b)

class C c a b where
    doc :: c a b -> a -> b

Funciona para una instancia de tipo multi-param:

instance C DF a b where
    doc (DF f) x = f x

Pero no funciona para los sinónimos tipo:

-- ERROR:
--
-- Type synonym `F' should have 2 arguments, but has been given none
-- In the instance declaration for `C F a b'
--
instance C F a b where
    doc f x = f x

¿Es posible definir una instancia de clase de tipo para F?


11
2018-04-17 12:24


origen


Respuestas:


No es posible como está escrito. Los sinónimos tipo deben, en general, aplicarse completamente para usarlos, especialmente como un parámetro de clase de tipo.

Tenga en cuenta que si puede eta-reducir el tipo de sinónimo suficiente una instancia es posible; es el sinónimo que debe aplicarse completamente, no el tipo al que se refiere. Entonces esto funcionaría

type F = (->)

instance C F a b where
    doc f x = f x

Ahi esta un LiberalTypeSynonyms extensión que relaja algunas de las reglas sobre la expansión de sinónimos de tipo, pero no ayuda aquí; solo le permite hacer cosas como dar un sinónimo de tipo parcialmente aplicado como un parámetro de tipo de otro tipo de sinónimo. Todo debe estar completamente expandido para usar de otra manera.

Para ver una razón por la cual esta restricción es necesaria, considere el siguiente sinónimo de tipo:

type Flip f a b = f b a

Y la siguiente instancia:

instance Functor (Flip Either a) where
    fmap _ (Right x) = Right x
    fmap f (Left x) = Left (f x)

Recuerde que también hay una instancia Functor (Either a) que hace lo mismo, excepto en espejo. Ambos son sensatos Functor instancias.

Teniendo en cuenta que a diferencia newtype, los sinónimos tipo se consideran los mismos que el tipo al que se refieren, ¿cuál debería ser el valor de la expresión? fmap not (Right True :: Either Bool Bool) ¿ser?


16
2018-04-17 12:37



Los sinónimos de tipo deben aplicarse por completo para que una instancia pueda definirse para ellos. El tipo de F no es * -> * -> *, como uno podría esperar, pero en cambio es inválido hasta que se proporcionen dos argumentos de tipo más. Tratar

type F = (->)

en lugar.


3
2018-04-17 12:38



Preguntas populares