Pergunta

Este código compila bem:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
  UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
  TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
  type Res a s b :: *

instance Sel a s b where
  type Res a s b = (s -> (b,s))

instance Sel a s (b->(c,a)) where
  type Res a s (b->(c,a)) = (b -> s -> (c,s))

Mas assim que eu adiciono o predicado do RHC falha:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances,
  UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables,
  TypeOperators, TypeSynonymInstances, TypeFamilies #-}
class Sel a s b where
  type Res a s b :: *

instance Sel a s b where
  type Res a s b = (s -> (b,s))

class R a where
  type Rec a :: *
  cons :: a -> Rec a
  elim :: Rec a -> a
instance Sel a s (b->(c,Rec a)) where
  type Res a s (b->(c,Rec a)) = (b -> s -> (c,s))

reclamando isso:

    Illegal type synonym family application in instance:
        b -> (c, Rec a)
    In the instance declaration for `Sel a s (b -> (c, Rec a))'

O que isso significa e (o mais importante) como faço para consertar isso?

Obrigado

Foi útil?

Solução

As famílias do tipo são unidirecionais: você pode expandir Rec a para o seu tipo calculado, mas você não pode (exclusivamente) ir da expansão de volta para Rec a. Isso torna as aplicações do tipo funções inadequadas, por exemplo, assinaturas, pois nunca podem acionar a instância a ser aplicada.

Você poderia tentar: em vez disso:

instance Rec a ~ reca => Sel a s (b->(c,reca))

Isso significa outra coisa: diz qualquer função b -> (c, reca) é uma instância e, em seguida, quando ele corresponde irrevogavelmente, o compilador verifica que Rec a ~ reca. Mas isso pode ser bom o suficiente para querer no seu caso.

Outras dicas

Rec não é um construtor de tipo; É uma função de tipo. Talvez você possa usá -lo apenas no tipo de valor da definição de tipo, não em uma declaração de classe? Estou supondo muito aqui; Não entendo todas as regras para as famílias do tipo.

Não sei como consertar, mas algumas coisas para tentar incluir:

  • Livre -se da classe sel e apenas defina type family Res a s b :: *. Usar type instance em vez do mecanismo de classe.

  • É quase possível que fazer tipo Rec injetivo usando data vai ajudar, mas acho que não.

  • Volte ao menor número de extensões de idiomas que possam funcionar - facilitará a ajuda de outras pessoas e também ajudará o compilador.

Isso significa que você não tem permissão para usar as famílias do tipo Synomym ao declarar instâncias de tipo. Veja a seção "Famílias do tipo e declarações de instância" do manual do GHC.

A única maneira de corrigi -lo é refatorar para não precisar de alguma forma.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top