Type family constraints at runtime // Couldn't match type `1 <=? n0' with 'True - haskell

StackOverflow!
For reasons that would like to remain between me and God, I'm currently playing around with promoting runtime naturals to the type level. I've been following this approach with GHC.TypeLits, which has worked out fine so far.
However, in one instance, I have an additional constraint of 1 <= n, i.e. my promoted natural not to be just any natural, but at least 1. This is also from GHC.TypeLits And I am unsure if/how it is possible to extract and make that information known.
Here's a minimal non-working example:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
import Data.Maybe
import Data.Proxy
import GHC.TypeLits
import Numeric.Natural
data AnyNat (n :: Nat) where
AN :: AnyNat n
data AtLeast1Nat (n :: Nat) where
AL1N :: AtLeast1Nat n
promote0 :: Natural -> AnyNat n
promote0 k = case sn of
SomeNat (_ :: Proxy p) -> AN
where
sn = (fromJust . someNatVal . toInteger) k
promote1 :: (KnownNat n, 1 <= n) => Natural -> AtLeast1Nat n
promote1 k = case sn of
SomeNat (_ :: Proxy p) -> AL1N
where
sn = (fromJust . someNatVal . toInteger) k
main :: IO ()
main = do nat_in <- getLine
let nat = read nat_in :: Natural
let p0 = promote0 nat
let p1 = promote1 nat
putStrLn "Last statement must be an expression"
This produces this error (full error here, but this is the relevant part):
* Couldn't match type `1 <=? n0' with 'True
arising from a use of `promote1'
The type variable `n0' is ambiguous
Honestly, this isn't too surprising and I (think I) do understand why this happens. The Natural that we give in could be any of them, so why would we be able to derive that 1 <= n? That's why it works fine for promote0 and not promote1.
My question is hence, is there any way to also check (and propagate to type-level) this information so I can use it as intended, or am I using the wrong approach here?

You're using the wrong approach.
As discussed in the comments, promote0 (and similarly promote1) isn't doing what you're hoping. The problem is that the AN on the right-hand-side of the case has type AnyNat n for some n entirely unrelated to the term sn. You could have written:
promote0 k = case 2+2 of 4 -> AN
and gotten much the same effect. Note the critical difference between your code and the other Stack Overflow answer you link: in that answer, the type variable n in the case scrutinee is used to type something (via ScopedTypeVariables) in the case branch. You bind a type variable p in your scrutinee but then don't use it for anything.
If we consider your actual problem, suppose we want to write something like this:
import qualified Data.Vector.Sized as V
main = do
n <- readLn :: IO Int
let Just v = V.fromList (replicate n 1)
v2 = v V.++ v
print $ v2
This won't type check. It gives an error on V.fromList about the lack of a KnownNat constraint. The issue is that v has been assigned a type S.Vector k Int for some k :: Nat. But V.fromList performs a runtime check that the length of the input list (the run time value n) is equal to the type-level k. To do this, k must be converted to a runtime integer which requires KnownNat k.
The general solution, as you've guessed, is to construct a SomeNat that basically contains a KnownNat n => n that's unknown at compile time. However, you don't want to try to promote it to a known type-level Nat (i.e., you don't want promote0). You want to leave it as-is and case match on it at the point you need its type-level value. That type-level value will be available within the case but unavailable outside the case, so no types that depend on n can "escape" the case statement.
So, for example, you can write:
import qualified Data.Vector.Sized as V
import Data.Proxy
import GHC.TypeNats
main = do
n <- readLn :: IO Int
-- keep `sn` as the type-level representation of the runtime `n`
let sn = someNatVal (fromIntegral n)
-- scrutinize it when you need its value at type level
case sn of
-- bind the contained Nat to the type variable `n`
SomeNat (Proxy :: Proxy n) -> do
-- now it's available at the type level
let v = V.replicate #n 1 -- using type-level "n"
v2 = v V.++ v
print v2
but you can't write:
main :: IO ()
main = do
n <- readLn :: IO Int
let sn = someNatVal (fromIntegral n)
let v2 = case sn of
SomeNat (Proxy :: Proxy n) ->
let v = V.replicate #n 1
in v V.++ v
print v2
You'll get an error that a type variable is escaping its scope. (If you want to let sized vectors leak outside the case, you need to make use of V.SomeSized or something similar.)
As for the main part of your question about handling a 1 <= n constraint, dealing with inequalities for type-level naturals is a major headache. I think you'll need to post a minimal example of exactly how you want to use this constraint in the context of a sized vector imlementation, in order to get a decent answer.

Related

Type-level constraints in Haskell

I'm trying to encode term algebra as a data type in Haskell for further use in an algorithm. By term algebra I mean a set of terms which are either variables or functions applied to other terms. The functions with zero arguments are constants (but that's actually does not matter here).
Firstly, one would need the following GHC language extensions to replicate my code:
{-# LANGUAGE GADTs, DataKinds,
TypeApplications,
TypeFamilies,
TypeOperators,
StandaloneKindSignatures,
UndecidableInstances#-}
and the following imports:
import qualified GHC.TypeLits as GTL
import Data.Kind
The direct way to encode terms (the first one I took):
data Term where
Var :: String -> Term
Func :: String -> Integer -> [Term] -> Term
where by String I want to encode the name, by Integer the arity and by [Terms] the list of arguments of a function.
Then I want to be sure that the list of terms as arguments have the same length as an arity.
The first idea is to use smart constructors, but I would like to encode such constraints on a type level. So the second idea would be to create type-level naturals, lists of a specified length and the data type where these numbers coincide:
data Z = Z
data S a = S a
data List n a where
Nil :: List Z a
Cons :: a -> List m a -> List (S m) a
data WWTerm where
WWVar :: String -> WWTerm
WWFunc :: String -> m -> List m WWTerm -> WWTerm
My question here is the following: is there a way to impose type-level constraints using ordinary lists at the same time via 1) creating special type-families, 2) creating special type classes, or 3) via constraints in data types?
Regarding my attempts, I wrote the following:
type MyLength :: [Type] -> GTL.Nat
type family MyLength xs where
MyLength '[] = 0
MyLength (x':xs) = 1 GTL.+ (MyLength xs)
data QFunc n l where
QFunc :: (MyLength l ~ n) => String -> (n :: GTL.Nat) -> l -> QFunc n l
Unfortunately, this part of code doesn't compile for the following reasons:
Expected a type, but ‘n :: Nat’ has kind ‘Nat’
...
Expected a type, but ‘l’ has kind ‘[*]’
...
Are there any thoughts on how to approach my goal?

Printing Dynamic Data

I have a system in haskell that uses Data.Dynamic and Type.Reflection to perform inference and calculations. I would like to be able to print the results.
Printing is easy when the type is supplied e.g
foo :: Dynamic -> String
foo dyn = case tyConName . someTypeRepTyCon . dynTypeRep $ dyn of
"Int" -> show $ fromDyn dyn (0 :: Int)
"Bool" -> show $ fromDyn dyn True
_ -> "no chance"
But if I want to be able to print tuples, I would have to add a new line for each e.g (Int, Bool), (Bool, Int), (Char, Int, Banana) ....
With the addition of more primitives and larger tuples this quickly becomes impractical.
Is there an algorithmic way to generate strings for this dynamic data, specifically for tuples and lists.
I like the main idea of the other answer, but it seems to get where it's going in a fairly roundabout way. Here's how I would style the same idea:
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE GADTs #-}
import Type.Reflection
import Data.Dynamic
showDyn :: Dynamic -> String
showDyn (Dynamic (App (App (eqTypeRep (typeRep #(,)) -> Just HRefl) ta) tb) (va, vb))
= concat [ "DynamicPair("
, showDyn (Dynamic ta va)
, ","
, showDyn (Dynamic tb vb)
, ")"
]
showDyn (Dynamic (eqTypeRep (typeRep #Integer) -> Just HRefl) n) = show n
showDyn (Dynamic tr _) = show tr
That first pattern match is quite a mouthful, but after playing with a few different ways of formatting it I'm convinced that there just is no way to make that look good. You can try it in ghci:
> showDyn (toDyn ((3,4), (True, "hi")))
"DynamicPair(DynamicPair(3,4),DynamicPair(Bool,[Char]))"
I could only manage to obtain this horrible solution.
{-# LANGUAGE GADTs, ScopedTypeVariables, TypeApplications #-}
{-# OPTIONS -Wall #-}
import Type.Reflection
import Data.Dynamic
Here we define the TyCon for (,) and Int. (I'm pretty sure there must be an easier way.)
pairTyCon :: TyCon
pairTyCon = someTypeRepTyCon (someTypeRep [('a','b')])
intTyCon :: TyCon
intTyCon = someTypeRepTyCon (someTypeRep [42 :: Int])
Then we dissect the Dynamic type. First we check if it is an Int.
showDynamic :: Dynamic -> String
showDynamic x = case x of
Dynamic tr#(Con k) v | k == intTyCon ->
case eqTypeRep tr (typeRep # Int) of
Just HRefl -> show (v :: Int)
_ -> error "It really should be an int"
-- to be continued
The above is ugly, since we first pattern match against the TyCon using == instead of pattern matching, which prevents the type refinement of v into an Int. So, we still have to resort to eqTypeRep to perform a second check which we already know has to succeed.
I think it could be made pretty by checking eqTypeRep in advance, for instance. Or fromDyn. It does not matter.
What matters is that the pair case below is even more messy, and can not be made pretty in the same way, as far as I can see.
-- continuing from above
Dynamic tr#(App (App t0#(Con k :: TypeRep p)
(t1 :: TypeRep a1))
(t2 :: TypeRep a2)) v | k == pairTyCon ->
withTypeable t0 $
withTypeable t1 $
withTypeable t2 $
case ( eqTypeRep tr (typeRep #(p a1 a2))
, eqTypeRep (typeRep #p) (typeRep #(,))) of
(Just HRefl, Just HRefl) ->
"DynamicPair("
++ showDynamic (Dynamic t1 (fst v))
++ ", "
++ showDynamic (Dynamic t2 (snd v))
++ ")"
_ -> error "It really should be a pair!"
_ -> "Dynamic: not an int, not a pair"
Above we match the TypeRep so that it represents something of type p a1 a2. We require that the representation of p to be pairTyCon.
As before this does not trigger type refinement, since it is done with == instead of pattern matching. We need to perform another explicit match to force p ~ (,) and another for the final refinement v :: (a1,a2). Sigh.
Finally, we can take fst v and snd v, turn them into Dynamic once again, and pair them. Effectively, we turned the original x :: Dynamic into something like (fst x, snd x) where both components are Dynamic. Now we can recurse.
I would really like to avoid the errors, but I can not see how to do that at the moment.
The redeeming part is that the approach is very general, and can be easily adapted to other type constructors.

How to satisfy constraints on existentially quantified values?

In an attempt at learning how to work with dependent data types in haskell I encountered the following problem:
Suppose you have a function such as:
mean :: ((1 GHC.TypeLits.<=? n) ~ 'True, GHC.TypeLits.KnownNat n) => R n -> ℝ
defined in the hmatrix library, then how do you use this on a vector that has an existential type? E.g.:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
import Data.Proxy (Proxy (..))
import GHC.TypeLits
import Numeric.LinearAlgebra.Static
getUserInput =
let userInput = 3 -- pretend it's unknown at compile time
seed = 42
in existentialCrisis seed userInput
existentialCrisis seed userInput
| userInput <= 0 = 0
| otherwise =
case someNatVal userInput of
Nothing -> undefined -- let's ignore this case for now
Just (SomeNat (proxy :: Proxy n)) ->
let someVector = randomVector seed Gaussian :: R n
in mean someVector -- I know that 'n > 0' but the compiler doesn't
This gives the following error:
• Couldn't match type ‘1 <=? n’ with ‘'True’
arising from a use of ‘mean’
Makes sense indeed, but after some googling and fiddling around, I could not find out how to deal with this. How can I get hold of an n :: Nat, based on user input, such that it satisfies the 1 <= n constraint?. I believe it must be possible since the someNatVal function already succeeds in satisfying the KnownNat constraint based on the condition that the input is not negative.
It seems to me that this is a common thing when working with dependent types, and maybe the answer is obvious but I don't see it.
So my question:
How, in general, can I bring an existential type in scope satisfying the constraints required for some function?
My attempts:
To my surprise, even the following modification
let someVector = randomVector seed Gaussian :: R (n + 1)
gave a type error:
• Couldn't match type ‘1 <=? (n + 1)’ with ‘'True’
arising from a use of ‘mean’
Also, adding an extra instance to <=? to prove this equality does not work as <=? is closed.
I tried an approach combining GADTs with typeclasses as in this answer to a previous question of mine but could not make it work.
Thanks #danidiaz for pointing me in the right direction, the typelist-witnesses documentation provides a nearly direct answer to my question. Seems like I was using the wrong search terms when googling for a solution.
So here is a self contained compileable solution:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Proxy (Proxy (..))
import Data.Type.Equality ((:~:)(Refl))
import GHC.TypeLits
import GHC.TypeLits.Compare
import Numeric.LinearAlgebra.Static
existentialCrisis :: Int -> Int -> IO (Double)
existentialCrisis seed userInput =
case someNatVal (fromIntegral userInput) of
Nothing -> print "someNatVal failed" >> return 0
Just (SomeNat (proxy :: Proxy n)) ->
case isLE (Proxy :: Proxy 1) proxy of
Nothing -> print "isLE failed" >> return 0
Just Refl ->
let someVector = randomVector seed Gaussian :: R n
in do
print userInput
-- I know that 'n > 0' and so does the compiler
return (mean someVector)
And it works with input only known at runtime:
λ: :l ExistentialCrisis.hs
λ: existentialCrisis 41 1
(0.2596687587224799 :: R 1)
0.2596687587224799
*Main
λ: existentialCrisis 41 0
"isLE failed"
0.0
*Main
λ: existentialCrisis 41 (-1)
"someNatVal failed"
0.0
It seems like typelist-witnesses does a lot unsafeCoerceing under the hood. But the interface is type-safe so it doesn't really matter that much for practical use cases.
EDIT:
If this question was of interest to you, might also find this post interesting: https://stackoverflow.com/a/41615278/2496293

TypeLits or Singletons: Promoting an `Integer` to `KnownNat` (`Nat`) at Runtime

I've found two ways to promote an Integer to a Nat (or KnownNat, I don't get the distintion yet) at runtime, either using TypeLits and Proxy (Data.Proxy and GHC.TypeLits), or Singletons (Data.Singletons). In the code below you can see how each of the two approaches is used:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Main where
import Prelude hiding (replicate)
import Data.Proxy (Proxy(Proxy))
import Data.Monoid ((<>))
import Data.Singletons (SomeSing(..), toSing)
import GHC.TypeLits
import Data.Singletons.TypeLits
import Data.Vector.Sized (Vector, replicate)
main :: IO ()
main = playingWithTypes 8
playingWithTypes :: Integer -> IO ()
playingWithTypes nn = do
case someNatVal nn of
Just (SomeNat (proxy :: Proxy n)) -> do
-- let (num :: Integer) = natVal proxy
-- putStrLn $ "Some num: " <> show num
putStrLn $ "Some vector: " <> show (replicate 5 :: Vector n Int)
Nothing -> putStrLn "There's no number, the integer was not a natural number"
case (toSing nn :: SomeSing Nat) of
SomeSing (SNat :: Sing n) -> do
-- let (num :: Integer) = natVal (Proxy :: Proxy n)
-- putStrLn $ "Some num: " <> show num
putStrLn $ "Some vector: " <> show (replicate 5 :: Vector n Int)
The documentation for TypeLits indicates that it shouldn't be used by developers, but Singletons don't capture the case in which the given Integer is not a natural number (i.e., running playingWithTypes 8 runs without errors, but playingWithTypes (-2) fails when we try to create a Singleton from the non-natural number).
So, what is the "standard" way to promote an Integer to a Nat? Or what is the best approach to promote, using TypeLits and Proxy, or Singletons?
Nat (or KnownNat, I don't get the distintion yet)
Nat is the kind of type-level natural numbers. It has no term-level inhabitants. The idea is that GHC promotes any natural number into the type-level, and gives it kind Nat.
KnownNat is a constraint, on something of kind Nat, whose implementation witnesses how to convert the thing of kind Nat to a term-level Integer. GHC automagically creates instances of KnownNat for all type-level inhabitants of the kind Nat1.
That said, even if every n :: Nat (read type n of kind Nat) has a KnownNat instance on it1, you still need to write out the constraint.
I've found two ways to promote an Integer to a Nat
Have you really? At the end of the day, Nat in today's GHC is simply magical. singletons taps into that same magic. Under the hood, it uses someNatVal.
So, what is the "standard" way to promote an Integer to a Nat? Or what is the best approach to promote, using GHC.TypeLits and Proxy, or singletons?
There is no standard way. My take is: use singletons when you can afford its dependency footprint and GHC.TypeLits otherwise. The advantage of singletons is that the SingI type class makes it convenient to do induction based analysis while still also relying on GHC's special Nat type.
1 As pointed out in the comments, not every inhabitant of the Nat kind has a KnownNat instance. For example, Any Nat :: Nat where Any is the one from GHC.Exts. Only the inhabitants 0, 1, 2, ... have KnownNat instances.

Set specific properties for data in Haskell

Let us say I want to make a ADT as follows in Haskell:
data Properties = Property String [String]
deriving (Show,Eq)
I want to know if it is possible to give the second list a bounded and enumerated property? Basically the first element of the list will be the minBound and the last element will be the maxBound. I am trying,
data Properties a = Property String [a]
deriving (Show, Eq)
instance Bounded (Properties a) where
minBound a = head a
maxBound a = (head . reverse) a
But not having much luck.
Well no, you can't do quite what you're asking, but maybe you'll find inspiration in this other neat trick.
{-# language ScopedTypeVariables, FlexibleContexts, UndecidableInstances #-}
import Data.Reflection -- from the reflection package
import qualified Data.List.NonEmpty as NE
import Data.List.NonEmpty (NonEmpty (..))
import Data.Proxy
-- Just the plain string part
newtype Pstring p = P String deriving Eq
-- Those properties you're interested in. It will
-- only be possible to produce bounds if there's at
-- least one property, so NonEmpty makes more sense
-- than [].
type Props = NonEmpty String
-- This is just to make a Show instance that does
-- what you seem to want easier to write. It's not really
-- necessary.
data Properties = Property String [String] deriving Show
Now we get to the key part, where we use reflection to produce class instances that can depend on run-time values. Roughly speaking, you can think of
Reifies x t => ...
as being a class-level version of
\(x :: t) -> ...
Because it operates at the class level, you can use it to parametrize instances. Since Reifies x t binds a type variable x, rather than a term variable, you need to use reflect to actually get the value back. If you happen to have a value on hand whose type ends in p, then you can just apply reflect to that value. Otherwise, you can always magic up a Proxy :: Proxy p to do the job.
-- If some Props are "in the air" tied to the type p,
-- then we can show them along with the string.
instance Reifies p Props => Show (Pstring p) where
showsPrec k p#(P str) =
showsPrec k $ Property str (NE.toList $ reflect p)
-- If some Props are "in the air" tied to the type p,
-- then we can give Pstring p a Bounded instance.
instance Reifies p Props => Bounded (Pstring p) where
minBound = P $ NE.head (reflect (Proxy :: Proxy p))
maxBound = P $ NE.last (reflect (Proxy :: Proxy p))
Now we need to have a way to actually bind types that can be passed to the type-level lambdas. This is done using the reify function. So let's throw some Props into the air and then let the butterfly nets get them back.
main :: IO ()
main = reify ("Hi" :| ["how", "are", "you"]) $
\(_ :: Proxy p) -> do
print (minBound :: Pstring p)
print (maxBound :: Pstring p)
./dfeuer#squirrel:~/src> ./WeirdBounded
Property "Hi" ["Hi","how","are","you"]
Property "you" ["Hi","how","are","you"]
You can think of reify x $ \(p :: Proxy p) -> ... as binding a type p to the value x; you can then pass the type p where you like by constraining things to have types involving p.
If you're just doing a couple of things, all this machinery is way more than necessary. Where it gets nice is when you're performing lots of operations with values that have phantom types carrying extra information. In many cases, you can avoid most of the explicit applications of reflect and the explicit proxy handling, because type inference just takes care of it all for you. For a good example of this technique in action, see the hyperloglog package. Configuration information for the HyperLogLog data structure is carried in a type parameter; this guarantees, at compile time, that only similarly configured structures are merged with each other.

Resources