Type synonyms with TemplateHaskell - haskell

If I have a type data Foo = Foo Int Int where frequently (but not always) the second parameter is a (fixed) function of the first, I could write a helper function mkFoo m = Foo m (f m) to reduce duplication.
I have this exact problem, but at the type level. The natural solution might be to use singletons to promote f, but my f isn't easily promoted. Instead, I'm trying to use TemplateHaskell and reflection to evaluate f at compile time at the data level. For example, I can currently do this (using ‑XDataKinds and GHC.TypeLits):
f :: Integer -> Integer
data Bar (a::Nat) (b::Nat)
mkNat :: Integer -> Q Type -- constructs a TypeLit
bar :: Bar 5 $(mkNat $ f $ proxy natValue (Proxy::Proxy 5))
It's obviously annoying to have to write this with a concrete type every time I want to use this pattern. Unfortunately, I know of no shorter or generic way to write the signature for bar. In particular, I can't define the type synonym
type Bar' (m :: Nat) = Bar m $(mkNat $ f $ proxy natVal (Proxy::Proxy m))
bar :: Bar' 5
due to TH stage restrictions (m is not imported or known when compiling the synonym).
Is there any way to simplify the signature of bar?

Related

Functor instance of kind *

I have newtype:
newtype Foo = Foo ([Int])
I would like to simply apply Int -> Int function over it like it is possible with fmap.
I thought it will be enough to derive or implement Functor instance, but it requires type of * -> * kind.
Is there some builtin way to make my type partially fmap-able?
https://hackage.haskell.org/package/mono-traversable-1.0.15.1/docs/Data-MonoTraversable.html#t:MonoFunctor
{-# LANGUAGE TypeFamilies #-}
type instance Element Foo = Int
instance MonoFunctor Foo where
-- omap :: (Int -> Int) -> Foo -> Foo
omap = ...
Before getting carried away, you should keep in mind that you're trying to avoid (1) naming and (2) writing the monomorphic function:
mapFoo :: (Int -> Int) -> (Foo -> Foo)
mapFoo f (Foo ints) = Foo (f <$> ints)
If you really don't want to give this function a separate name and want GHC to write the function for you, I think the only sensible way is to re-define your type as a proper functor of kind * -> * with an automatically derived instance:
newtype FooF a = Foo [a] deriving (Functor)
and then define a type alias for the specialization to Int:
type Foo = FooF Int
This is not precisely equivalent to your original definition of Foo. In particular, the following expression in isolation:
Foo [1,2,3]
will have type Num a => FooF a instead of type Foo = FooF Int, so GHC may fail to infer types in all the places it used to. But, this Foo type alias will mostly behave like your original Foo newtype and will allow you to write:
fmap (*5) $ Foo [1,2,3]
and such.
On the other hand, if you want to keep your newtype the same, don't mind writing the function yourself, yet don't want to give that function a separate name, you can't use fmap (at least not without overriding the prelude definition, which kind of defeats the purpose). However, as per #leftroundabout's answer, you can use omap from the mono-traversable package. Because this requires you to define the function yourself in a MonoFunctor Foo instance (e.g., using the same definition as mapFoo above), there's no real point unless you're doing this for a bunch of non-functors besides Foo and want to use a single omap name for all of them or want to write functions that can handle any such MonoFunctor uniformly.

Using makeLenses, class constraints and type synonyms together

I'm quite new to Haskell and want to use makeLenses from Control.Lens and class constraints together with type synonyms to make my functions types more compact (readable?).
I've tried to come up with a minimal dummy example to demonstrate what I want to achieve and the example serves no other purpose than this.
At the end of this post I've added an example closer to my original problem if you are interested in the context.
Minimal example
As an example, say I define the following data type:
data State a = State { _a :: a
} deriving Show
, for which I also make lenses:
makeLenses ''State
In order to enforce a class constraint on the type parameter a used by the type constructor State I use a smart constructor:
mkState :: (Num a) => a -> State a
mkState n = State {_a = n}
Next, say I have a number of functions with type signatures similar to this:
doStuff :: Num a => State a -> State a
doStuff s = s & a %~ (*2)
This all works as intended, for example:
test = doStuff . mkState $ 5.5 -- results in State {_a = 11.0}
Problem
I've tried to use the following type synonym:
type S = (Num n) => State n -- Requires the RankNTypes extensions
, together with:
{-# LANGUAGE RankNTypes #-}
, in an attempt to simplify the type signature of doStuff:
doStuff :: S -> S
, but this gives the following error:
Couldn't match type `State a0' with `forall n. Num n => State n'
Expected type: a0 -> S
Actual type: a0 -> State a0
In the second argument of `(.)', namely `mkState'
In the expression: doStuff . mkState
In the expression: doStuff . mkState $ 5.5
Failed, modules loaded: none.
Question
My current knowledge of Haskell is not sufficient to understand what causes the above error. I hope someone can explain what causes the error and/or suggest other ways to construct the type synonym or why such a type synonym is not possible.
Background
My original problem looks closer to this:
data State r = State { _time :: Int
, _ready :: r
} deriving Show
makeLenses ''State
data Task = Task { ... }
Here I want to enforce the type of _ready being an instance of the Queue class using the following smart constructor:
mkState :: (Queue q) => Int -> q Task -> State (q Task)
mkState t q = State { _time = t
, _ready = q
}
I also have a number of functions with type signatures similar to this:
updateState :: Queue q => State (q Task) -> Task -> State (q Task)
updateState s x = s & ready %~ (enqueue x) & time %~ (+1)
I would like to use a type synonym S to be able to rewrite the type of such functions as:
updateState :: S -> Task -> S
, but as with the first minimal example I don't know how to define the type synonym S or whether it is possible at all.
Maybe there is no real benefit in trying to simplify the type signatures?
Related reading
I've read the following related questions on SO:
Class constraints for data records
Are type synonyms with typeclass constraints possible?
This might also be related but given my current understanding of Haskell I cannot really understand all of it:
Unifying associated type synonyms with class constraints
Follow-up
It's been a while since I've had the opportunity to do some Haskell. Thanks to #bheklilr I've now managed to introduce a type synonym only to hit the next type error I'm still not able to understand. I've posted the following follow-up question Type synonym causes type error regarding the new type error.
You see that error in particular because of the combination of the . operator and your use of RankNTypes. If you change it from
test = doStuff . mkState $ 5.5
to
test = doStuff $ mkState 5.5
or even
test = doStuff (mkState 5.5)
it will compile. Why is this? Look at the types:
doStuff :: forall n. Num n => State n -> State n
mkState :: Num n => n -> State n
(doStuff) . (mkState) <===> (forall n. Num n => State n -> State n) . (Num n => n -> State n)
Hopefully the parentheses help make it clear here, the n from forall n. Num n ... for doStuff is a different type variable from the Num n => ... for mkState because the scope of the forall only extends to the end of the parentheses. So these functions can't actually compose because the compiler sees them as separate types! There are actually special rules for the $ operator specifically for using the ST monad precisely for this reason, just so you can do runST $ do ....
You may be able to accomplish what you want easier using GADTs, but I don't believe lens' TemplateHaskell will work with GADT types. However, you can write your own pretty easily in this case, so it isn't that big of a deal.
A further explanation:
doStuff . mkState $ 5.5
is very different than
doStuff $ mkState 5.5
In the first one, doStuff says that for all Num types n, its type is State n -> State n, whereas mkState says for some Num type m, its type is m -> State m. These two types are not the same because of the "for all" and "for some" quantifications (hence ExistentialQuantification), since composing them would mean that for some Num m you can produce all Num n.
In the doStuff $ mkState 5.5, you have the equivalent of
(forall n. Num n => State n -> State n) $ (Num m => State m)
Notice that the type after the $ is not a function because mkState 5.5 is fully applied. So this works because for all Num n you can do State n -> State n, and you're providing it some Num m => State m. This works intuitively. Again, the difference here is the composition versus application. You can't compose a function that works on some types with a function that works on all types, but you can pass a value to a function that works on all types ("all types" here meaning forall n. Num n => n).

When are type signatures necessary in Haskell?

Many introductory texts will tell you that in Haskell type signatures are "almost always" optional. Can anybody quantify the "almost" part?
As far as I can tell, the only time you need an explicit signature is to disambiguate type classes. (The canonical example being read . show.) Are there other cases I haven't thought of, or is this it?
(I'm aware that if you go beyond Haskell 2010 there are plenty for exceptions. For example, GHC will never infer rank-N types. But rank-N types are a language extension, not part of the official standard [yet].)
Polymorphic recursion needs type annotations, in general.
f :: (a -> a) -> (a -> b) -> Int -> a -> b
f f1 g n x =
if n == (0 :: Int)
then g x
else f f1 (\z h -> g (h z)) (n-1) x f1
(Credit: Patrick Cousot)
Note how the recursive call looks badly typed (!): it calls itself with five arguments, despite f having only four! Then remember that b can be instantiated with c -> d, which causes an extra argument to appear.
The above contrived example computes
f f1 g n x = g (f1 (f1 (f1 ... (f1 x))))
where f1 is applied n times. Of course, there is a much simpler way to write an equivalent program.
Monomorphism restriction
If you have MonomorphismRestriction enabled, then sometimes you will need to add a type signature to get the most general type:
{-# LANGUAGE MonomorphismRestriction #-}
-- myPrint :: Show a => a -> IO ()
myPrint = print
main = do
myPrint ()
myPrint "hello"
This will fail because myPrint is monomorphic. You would need to uncomment the type signature to make it work, or disable MonomorphismRestriction.
Phantom constraints
When you put a polymorphic value with a constraint into a tuple, the tuple itself becomes polymorphic and has the same constraint:
myValue :: Read a => a
myValue = read "0"
myTuple :: Read a => (a, String)
myTuple = (myValue, "hello")
We know that the constraint affects the first part of the tuple but does not affect the second part. The type system doesn't know that, unfortunately, and will complain if you try to do this:
myString = snd myTuple
Even though intuitively one would expect myString to be just a String, the type checker needs to specialize the type variable a and figure out whether the constraint is actually satisfied. In order to make this expression work, one would need to annotate the type of either snd or myTuple:
myString = snd (myTuple :: ((), String))
In Haskell, as I'm sure you know, types are inferred. In other words, the compiler works out what type you want.
However, in Haskell, there are also polymorphic typeclasses, with functions that act in different ways depending on the return type. Here's an example of the Monad class, though I haven't defined everything:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
fail :: String -> m a
We're given a lot of functions with just type signatures. Our job is to make instance declarations for different types that can be treated as Monads, like Maybe t or [t].
Have a look at this code - it won't work in the way we might expect:
return 7
That's a function from the Monad class, but because there's more than one Monad, we have to specify what return value/type we want, or it automatically becomes an IO Monad. So:
return 7 :: Maybe Int
-- Will return...
Just 7
return 6 :: [Int]
-- Will return...
[6]
This is because [t] and Maybe have both been defined in the Monad type class.
Here's another example, this time from the random typeclass. This code throws an error:
random (mkStdGen 100)
Because random returns something in the Random class, we'll have to define what type we want to return, with a StdGen object tupelo with whatever value we want:
random (mkStdGen 100) :: (Int, StdGen)
-- Returns...
(-3650871090684229393,693699796 2103410263)
random (mkStdGen 100) :: (Bool, StdGen)
-- Returns...
(True,4041414 40692)
This can all be found at learn you a Haskell online, though you'll have to do some long reading. This, I'm pretty much 100% certain, it the only time when types are necessary.

Binary instance for an existential

Given an existential data type, for example:
data Foo = forall a . (Typeable a, Binary a) => Foo a
I'd like to write instance Binary Foo. I can write the serialisation (serialise the TypeRep then serialise the value), but I can't figure out how to write the deserialisation. The basic problem is that given a TypeRep you need to map back to the type dictionary for that type - and I don't know if that can be done.
This question has been asked before on the haskell mailing list http://www.haskell.org/pipermail/haskell/2006-September/018522.html, but no answers were given.
You need some way that each Binary instance can register itself (just as in your witness version). You can do this by bundling each instance declaration with an exported foreign symbol, where the symbol name is derived from the TypeRep. Then when you want to deserialize you get the name from the TypeRep and look up that symbol dynamically (with dlsym() or something similar). The value exported by the foreign export can, e.g., be the deserializer function.
It's crazy ugly, but it works.
This can be solved in GHC 7.10 and onwards using the Static Pointers Language extension:
{-# LANGUAGE StaticPointers #-}
{-# LANGUAGE InstanceSigs #-}
data Foo = forall a . (StaticFoo a, Binary a, Show a) => Foo a
class StaticFoo a where
staticFoo :: a -> StaticPtr (Get Foo)
instance StaticFoo String where
staticFoo _ = static (Foo <$> (get :: Get String))
instance Binary Foo where
put (Foo x) = do
put $ staticKey $ staticFoo x
put x
get = do
ptr <- get
case unsafePerformIO (unsafeLookupStaticPtr ptr) of
Just value -> deRefStaticPtr value :: Get Foo
Nothing -> error "Binary Foo: unknown static pointer"
A full description of the solution can be found on this blog post, and a complete snippet here.
If you could do that, you would also be able to implement:
isValidRead :: TypeRep -> String -> Bool
This would be a function that changes its behavior due to someone defining a new type! Not very pure-ish.. I think (and hope) that one can't implement this in Haskell..
I have an answer that slightly works in some situations (not enough for my purposes), but may be the best that can be done. You can add a witness function to witness any types that you have, and then the deserialisation can lookup in the witness table. The rough idea is (untested):
witnesses :: IORef [Foo]
witnesses = unsafePerformIO $ newIORef []
witness :: (Typeable a, Binary a) => a -> IO ()
witness x = modifyIORef (Foo x :)
instance Binary Foo where
put (Foo x) = put (typeOf x) >> put x
get = do
ty <- get
wits <- unsafePerformIO $ readIORef witnesses
case [Foo x | Foo x <- wits, typeOf x == ty] of
Foo x:_ -> fmap Foo $ get `asTypeOf` return x
[] -> error $ "Could not find a witness for the type: " ++ show ty
The idea is that as you go through, you call witness on values of every type that you may plausibly encounter when deserialising. When you deserialise you search this list. The obvious problem is that if you fail to call witness before deserialisation you get a crash.

Haskell get type of algebraic parameter

I have a type
class IntegerAsType a where
value :: a -> Integer
data T5
instance IntegerAsType T5 where value _ = 5
newtype (IntegerAsType q) => Zq q = Zq Integer deriving (Eq)
newtype (Num a, IntegerAsType n) => PolyRing a n = PolyRing [a]
I'm trying to make a nice "show" for the PolyRing type. In particular, I want the "show" to print out the type 'a'. Is there a function that returns the type of an algebraic parameter (a 'show' for types)?
The other way I'm trying to do it is using pattern matching, but I'm running into problems with built-in types and the algebraic type.
I want a different result for each of Integer, Int and Zq q.
(toy example:)
test :: (Num a, IntegerAsType q) => a -> a
(Int x) = x+1
(Integer x) = x+2
(Zq x) = x+3
There are at least two different problems here.
1) Int and Integer are not data constructors for the 'Int' and 'Integer' types. Are there data constructors for these types/how do I pattern match with them?
2) Although not shown in my code, Zq IS an instance of Num. The problem I'm getting is:
Ambiguous constraint `IntegerAsType q'
At least one of the forall'd type variables mentioned by the constraint
must be reachable from the type after the '=>'
In the type signature for `test':
test :: (Num a, IntegerAsType q) => a -> a
I kind of see why it is complaining, but I don't know how to get around that.
Thanks
EDIT:
A better example of what I'm trying to do with the test function:
test :: (Num a) => a -> a
test (Integer x) = x+2
test (Int x) = x+1
test (Zq x) = x
Even if we ignore the fact that I can't construct Integers and Ints this way (still want to know how!) this 'test' doesn't compile because:
Could not deduce (a ~ Zq t0) from the context (Num a)
My next try at this function was with the type signature:
test :: (Num a, IntegerAsType q) => a -> a
which leads to the new error
Ambiguous constraint `IntegerAsType q'
At least one of the forall'd type variables mentioned by the constraint
must be reachable from the type after the '=>'
I hope that makes my question a little clearer....
I'm not sure what you're driving at with that test function, but you can do something like this if you like:
{-# LANGUAGE ScopedTypeVariables #-}
class NamedType a where
name :: a -> String
instance NamedType Int where
name _ = "Int"
instance NamedType Integer where
name _ = "Integer"
instance NamedType q => NamedType (Zq q) where
name _ = "Zq (" ++ name (undefined :: q) ++ ")"
I would not be doing my Stack Overflow duty if I did not follow up this answer with a warning: what you are asking for is very, very strange. You are probably doing something in a very unidiomatic way, and will be fighting the language the whole way. I strongly recommend that your next question be a much broader design question, so that we can help guide you to a more idiomatic solution.
Edit
There is another half to your question, namely, how to write a test function that "pattern matches" on the input to check whether it's an Int, an Integer, a Zq type, etc. You provide this suggestive code snippet:
test :: (Num a) => a -> a
test (Integer x) = x+2
test (Int x) = x+1
test (Zq x) = x
There are a couple of things to clear up here.
Haskell has three levels of objects: the value level, the type level, and the kind level. Some examples of things at the value level include "Hello, world!", 42, the function \a -> a, or fix (\xs -> 0:1:zipWith (+) xs (tail xs)). Some examples of things at the type level include Bool, Int, Maybe, Maybe Int, and Monad m => m (). Some examples of things at the kind level include * and (* -> *) -> *.
The levels are in order; value level objects are classified by type level objects, and type level objects are classified by kind level objects. We write the classification relationship using ::, so for example, 32 :: Int or "Hello, world!" :: [Char]. (The kind level isn't too interesting for this discussion, but * classifies types, and arrow kinds classify type constructors. For example, Int :: * and [Int] :: *, but [] :: * -> *.)
Now, one of the most basic properties of Haskell is that each level is completely isolated. You will never see a string like "Hello, world!" in a type; similarly, value-level objects don't pass around or operate on types. Moreover, there are separate namespaces for values and types. Take the example of Maybe:
data Maybe a = Nothing | Just a
This declaration creates a new name Maybe :: * -> * at the type level, and two new names Nothing :: Maybe a and Just :: a -> Maybe a at the value level. One common pattern is to use the same name for a type constructor and for its value constructor, if there's only one; for example, you might see
newtype Wrapped a = Wrapped a
which declares a new name Wrapped :: * -> * at the type level, and simultaneously declares a distinct name Wrapped :: a -> Wrapped a at the value level. Some particularly common (and confusing examples) include (), which is both a value-level object (of type ()) and a type-level object (of kind *), and [], which is both a value-level object (of type [a]) and a type-level object (of kind * -> *). Note that the fact that the value-level and type-level objects happen to be spelled the same in your source is just a coincidence! If you wanted to confuse your readers, you could perfectly well write
newtype Huey a = Louie a
newtype Louie a = Dewey a
newtype Dewey a = Huey a
where none of these three declarations are related to each other at all!
Now, we can finally tackle what goes wrong with test above: Integer and Int are not value constructors, so they can't be used in patterns. Remember -- the value level and type level are isolated, so you can't put type names in value definitions! By now, you might wish you had written test' instead:
test' :: Num a => a -> a
test' (x :: Integer) = x + 2
test' (x :: Int) = x + 1
test' (Zq x :: Zq a) = x
...but alas, it doesn't quite work like that. Value-level things aren't allowed to depend on type-level things. What you can do is to write separate functions at each of the Int, Integer, and Zq a types:
testInteger :: Integer -> Integer
testInteger x = x + 2
testInt :: Int -> Int
testInt x = x + 1
testZq :: Num a => Zq a -> Zq a
testZq (Zq x) = Zq x
Then we can call the appropriate one of these functions when we want to do a test. Since we're in a statically-typed language, exactly one of these functions is going to be applicable to any particular variable.
Now, it's a bit onerous to remember to call the right function, so Haskell offers a slight convenience: you can let the compiler choose one of these functions for you at compile time. This mechanism is the big idea behind classes. It looks like this:
class Testable a where test :: a -> a
instance Testable Integer where test = testInteger
instance Testable Int where test = testInt
instance Num a => Testable (Zq a) where test = testZq
Now, it looks like there's a single function called test which can handle any of Int, Integer, or numeric Zq's -- but in fact there are three functions, and the compiler is transparently choosing one for you. And that's an important insight. The type of test:
test :: Testable a => a -> a
...looks at first blush like it is a function that takes a value that could be any Testable type. But in fact, it's a function that can be specialized to any Testable type -- and then only takes values of that type! This difference explains yet another reason the original test function didn't work. You can't have multiple patterns with variables at different types, because the function only ever works on a single type at a time.
The ideas behind the classes NamedType and Testable above can be generalized a bit; if you do, you get the Typeable class suggested by hammar above.
I think now I've rambled more than enough, and likely confused more things than I've clarified, but leave me a comment saying which parts were unclear, and I'll do my best.
Is there a function that returns the type of an algebraic parameter (a 'show' for types)?
I think Data.Typeable may be what you're looking for.
Prelude> :m + Data.Typeable
Prelude Data.Typeable> typeOf (1 :: Int)
Int
Prelude Data.Typeable> typeOf (1 :: Integer)
Integer
Note that this will not work on any type, just those which have a Typeable instance.
Using the extension DeriveDataTypeable, you can have the compiler automatically derive these for your own types:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Typeable
data Foo = Bar
deriving Typeable
*Main> typeOf Bar
Main.Foo
I didn't quite get what you're trying to do in the second half of your question, but hopefully this should be of some help.

Resources