I work with the data types of this form using V from linear :
type Foo n = V (n * 3) Double -> Double
Fixed to n , this is very important because I want to be able to ensure that I go through the right amount of elements at compile time. This is part of my program that is already working well, regardless of what I'm doing here.
For any KnownNat n I can generate a Foo n that satisfies the behavior that my program requires. For the purposes of this question it may be something stupid like
mkFoo :: KnownNat (n * 3) => Foo n mkFoo = sum
Or for a more meaningful example, it can generate a random V the same length and use dot for the two. The KnownNat restriction is redundant here, but in fact it needs to make Foo . I make one Foo and use it for my entire program (or with multiple inputs), so this guarantees me that whenever I use it, I use things with the same length and on what the Foo structure dictates.
And finally, I have a function that introduces inputs for Foo :
bar :: KnownNat (n * 3) => Proxy n -> [V (n * 3) Double]
bar is actually the reason that I use n * 3 as a type function, rather than just manually extending it. The reason is that bar can do its job using three vectors of length n and attaching them all together as a vector of length n * 3 . In addition, n is a much more significant parameter for a function, semantically than n * 3 . It also allows me to forbid invalid values ββlike n which are not a multiple of 3, etc.
Now, before, everything worked fine, as long as I defined the type synonym at the beginning:
type N = 5
And I can just pass Proxy :: Proxy N to bar and use mkFoo :: Foo N And it worked fine.
-- works fine doStuff :: [Double] doStuff = let inps = bar (Proxy :: Proxy N) in map (mkFoo :: Foo N) inps
But now I want to configure n at run time, loading information from a file or from command line arguments.
I tried to do this by calling reflectNat :
doStuff :: Integer -> Double doStuff n = reflectNat 5 $ \ pn@ (Proxy :: Proxy n) -> let inps = bar (Proxy :: Proxy n) in map (mkFoo :: Foo n) inps
But ... bar and mkFoo require KnownNat (n * 3) , but reflectNat just gives me KnownNat n .
Is there any way to generalize the proof that reflectNat allows me to satisfy Foo ?