0

I have an interface that depends on another interface, with some dependent types, and I can't get the compiler to constrain a type in a related function

import Data.Vect

interface Distribution (0 event : Nat) (dist : Nat -> Nat -> Type) where

data Gaussian : Nat -> Nat -> Type where

Distribution e Gaussian where

interface Distribution targets marginal =>
 Model (targets : Nat) (marginal : Nat -> Nat -> Type) model where
  marginalise : model -> Vect s Double -> marginal targets s

foo : m -> Model 1 Gaussian m => Vect s Double -> Nat
foo model x = let marginal = marginalise model x in ?rhs

I get

While processing right hand side of foo. Can't find an implementation for Model ?targets ?marginal m.

foo model x = let marginal = marginalise model x in ?rhs  
                             ^^^^^^^^^^^^^^^^^^^

How could this be?

If I use marginalise {marginal=Gaussian} {targets=1} model x it type checks, but I don't get why this isn't already determined by the type signature.

I don't think this qu I asked about the same area applies here

joel
  • 6,359
  • 2
  • 30
  • 55
  • There's no fundep from `model` to `marginal` or `targets` in `Model`, and the type of `marginal` in `foo` isn't constrained in any way (its type is `marginal targets s` for some choice of `marginal`, `targets` and `s`), so it has no reason to pick any particular choice of `targets` and `marginal` just because you happen to have one particular instance for one particular choice in scope. – Cactus Aug 10 '21 at 02:24
  • @Cactus ok thanks. It seems constraints in idris work quite differently to how they do in python/scala. You talk of "having an instance in scope" rather than a constraint, too, as though `Model 1 Gaussian m =>` isn't really a constraint. Have I got that right? If so, how do I make such a constraint? – joel Aug 10 '21 at 09:00

1 Answers1

1

I started writing this as a comment and realized halfway through that it might work as a full-blown answer.

Model 1 Gaussan m means that you have an implementation of the Model interface with targets = 1, marginal = Gaussian and model = m. Then, the let-binding of marginal requires Model a b m, i.e. an implementation of Model where targets = a , marginal = b and model = m. But there is no requirement that a = 1 and b = Gaussian!

My guess is that once you read up on determining parameters, you will discover that you want something like:

interface Distribution targets marginal =>
 Model (targets : Nat) (marginal : Nat -> Nat -> Type) model | model where
Cactus
  • 27,075
  • 9
  • 69
  • 149