edit: eu tenho seguido com uma pergunta específica. Obrigado respondentes aqui, e eu acho que o acompanhamento pergunta faz um trabalho melhor de explicar alguma confusão que eu apresentei aqui.
TL;DR eu estou lutando para obter provas de restrições de expressões, enquanto o uso de GADTs com existencial restrições sobre os construtores. (é um bocado grave, desculpe!)
Eu já destilada, um problema para o seguinte. Eu tenho um simples GADT que representa os pontos de chamada X
função e aplicações de chamada F
. Pontos X
são constrangido a ser Objects
.
data GADT ix a where
X :: Object ix a => a -> GADT ix a
F :: (a -> b) -> GADT ix a -> GADT ix b
Constrained
refere-se a recipientes cujos objetos são restringidos por algo e Object
é que algo. (edit: o meu real problema envolve Category
e Cartesian
classes de restrita-categorias)
-- | I can constrain the values within containers of kind `* -> *`
class Constrained (ix :: * -> *) where
type Object ix a :: Constraint
-- | Here's a trivial constraint. A more interesting one might include `Typeable a`, for ex
instance Constrained (GADT ix) where
type Object (GADT ix) a = (Constrained ix, Object ix a)
Eu gostaria de escrever uma expressão:
-- error: Could not deduce: Object ix Int arising from a use of ‘X’
ex0 :: GADT ix String
ex0 = F show (X (3 :: Int))
E enquanto a solução óbvia funciona, ele rapidamente se torna detalhado quando a construção de maiores expressões:
-- Typechecks, but eventually verbose
ex1 :: Object ix Int => GADT ix String
ex1 = F show (X (3 :: Int))
Eu acho que a solução correta deve ser algo como isto:
-- error: Could not deduce: Object ix Int arising from a use of ‘X’
ex2 :: Constrained ix => GADT ix String
ex2 = F show (X (3 :: Int))
Mas eu ainda não consigo obter essa prova de Object ix Int
.
Eu tenho certeza que é mais simples do que eu estou pensando. Eu tentei adicionar restrições para o Object
restrição de família no GADT
instância de classe. Eu tentei oferecendo restrições na expressão da assinatura. Eu tentei QuantifiedConstraints
embora, eu não tenho certeza se completamente compreendê-lo ainda. Por favor, ajude-me sábios!
Runnable:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE InstanceSigs #-}
module Test where
import Data.Kind
import Data.Functor.Identity
import Data.Functor.Const
-- | I can constrain the values within containers of kind `* -> *`
class Constrained (ix :: * -> *) where
type Object ix a :: Constraint
-- | Here's a trivial constraint. A more interesting one might include `Typeable a`, for instance
instance Constrained (GADT ix) where
type Object (GADT ix) a = (Constrained ix, Object ix a)
-- | A demo GADT that has function application ('F'), and points ('X'). The
-- points are constrained.
data GADT ix a where
X :: Object ix a => a -> GADT ix a
F :: (a -> b) -> GADT ix a -> GADT ix b
-- -- Broken
-- -- error: Could not deduce: Object ix Int arising from a use of ‘X’
-- ex0 :: GADT ix String
-- ex0 = F show (X (3 :: Int))
-- Typechecks
-- but for larger programs becomes verbose, requiring many explicit constraints
ex1 :: Object ix Int => GADT ix String
ex1 = F show (X (3 :: Int))
-- -- What I want, but, it's broken
-- ex2 :: Constrained ix => GADT ix String
-- ex2 = F show (X (3 :: Int))
YourFunc
, que iria introduzir uma tonelada de frente caldeiras (um novo prelúdio), embora, provavelmente, eliminar a futura clichê. WrtInferrenceChain
, Eu estou lutando para mapear para o meu problema, mas, talvez, o acompanhamento ajuda a explicar melhor? Obrigado btw!