How can I give the type inference engine some hints? - class

In (very) modern GHC's, I can write this:
{-# LANGUAGE TypeFamilies #-}
-- consider this part "library" code, changeable at will
data Container a = Container
data Element
class Foo a where foo :: a -> Int
instance Element ~ a => Foo (Container a) where foo _ = 0
-- consider this part "client" code; bonus points if it can remain exactly as is
main = print (foo Container)
Salient points:
The client code did not require any additional type signatures.
Container, which is a polymorphic value (of type Container a), was correctly monomorphed to Container Element.
No newtype wrappers were required in the client code.
It is probably not possible to declare another instance of Foo whose outermost type constructor is Container. This is not a property I care about preserving in the following discussion.
Can this be done in a more backwards-compatible way? My first attempt looked like this:
{-# LANGUAGE FlexibleInstances #-}
data Container a = Container
data Element
class Foo a where foo :: a -> Int
instance Foo (Container Element) where foo _ = 0
main = print (foo Container)
...which gives an error:
test.hs:8:15:
No instance for (Foo (Container a0))
arising from a use of `foo'
Possible fix: add an instance declaration for (Foo (Container a0))
In the first argument of `print', namely `(foo Container)'
In the expression: print (foo Container)
In an equation for `main': main = print (foo Container)
I realized that this error probably arises because the instance doesn't use a type variable as the argument to Container, so I also tried:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}
data Container a = Container
data Element
class Foo a where foo :: a -> Int
instance Convertible a Element => Foo (Container a) where foo _ = 0
class Convertible a b where
-- convert is not necessary in this tiny example, but it would
-- be necessary in my not-so-tiny use case
convert :: Container a -> Container b
instance Convertible a a where
convert = id
main = print (foo Container)
But this just pushes the problem to the Convertible type class:
test.hs:14:19:
No instance for (Convertible a0 Element)
arising from a use of `foo'
Possible fix:
add an instance declaration for (Convertible a0 Element)
In the first argument of `print', namely `(foo Container)'
In the expression: print (foo Container)
In an equation for `main': main = print (foo Container)
A similar error arises from writing an instance for Convertible Element Element instead of Convertible a a. My last-ditch attempt was to specialize even further:
data Container a = Container
data Element
class Foo a where foo :: a -> Int
instance IsElement a => Foo (Container a) where foo _ = 0
class IsElement a where
convert :: a -> Element
instance IsElement Element where
convert = id
main = print (foo Container)
...which has the notable benefit of being H98, but the notable downside of still not quite working:
test.hs:10:19:
Ambiguous type variable `a0' in the constraint:
(IsElement a0) arising from a use of `foo'
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `print', namely `(foo Container)'
In the expression: print (foo Container)
In an equation for `main': main = print (foo Container)
So, the question is this: is there some similar implementation that achieves properties 1, 2, and 3 above, yet does not require the type equality operator?
edit I thought rank-2 types might help:
{-# LANGUAGE FlexibleInstances, RankNTypes #-}
data Container a = Container
data Element
class Foo a where foo :: a -> Int
instance Foo (forall a. Container a) where foo _ = 0
main = print (foo Container)
...but alas, still no dice:
test.hs:6:14:
Illegal polymorphic or qualified type: forall a. Container a
In the instance declaration for `Foo (forall a. Container a)'

I don't understand what you're trying to do here. In particular, why do you care that Container is polymorphic when you only want the client to work with Container Element?
That said, how about using a different kind for the type class?
data Container a = Container
data Element
class Foo a where foo :: a x -> Int
instance Foo Container where foo _ = 0
Now it truly doesn't matter which type Container is instantiated to.
If this doesn't work, I suspect the answer is "no, you can't do precisely what you want." Although you could export container = Container :: Container Element and have client code use that instead of Container.
Edit: given the full context, and that rank-2 types aren't possible either, I am reasonably certain that there isn't a solution given the problem constraints. The best workaround I can think of is creating a new function xcast :: XConfig a -> XConfig Layout. This would allow you to write instance Binding (XConfig a -> Foo).

Related

newtype vs foreign import data

What are the practical reasons of choosing between these options?
For example:
foreign import data Foo :: Type -> Type
newtype Foo a = Foo a
Let's assume in both cases, we get a Foo via some function:
foreign import newFoo :: forall a. a -> Foo a
The difference is that with newtype the data representation is known, and with foreign import it isn't.
One consequence of this is that with newtype you can get a out of Foo a by pattern matching:
let foo = newFoo 42
let (Foo fourtyTwo) = foo
and with foreign import you can't do that.
Another consequence is that with foreign import the function newFoo is free to choose representation, it doesn't necessarily have to be equivalent to that of a, e.g.:
// JavaScript
exports.newFoo = function (a) { return { wrapped: a } }
but with newtype is has to be exactly a:
// JavaScript
exports.newFoo = function (a) { return a }
Then there is also the convenience of automatically deriving the Newtype class, which opens up some automation possibilities.
To respond to the second question in the comments (in the future please post a separate question):
If your Foo did not have a type parameter, but was defined like this:
// Case 1
data Foo = Foo
// Case 2
foreign import data Foo :: Type
foreign import newFoo :: Foo
The difference here is the same as above: for data representation is known, for foreign import it isn't.
The way it can manifest in practice really depends on your context. One example I can think of is automatic derivation of Eq, Show, Generic, etc., which would need to be manually coded for the foreign import approach. Another example that comes to mind is that data Foo is statically guaranteed to have exactly one value, whereas newFoo is free to return different values in every call.

What is the difference between F[A] and A?

For languages like Scala and Haskell, you can construct types using type constructors. What is the right vocabulary for differentiating between all of these parts?
A is a type. F[A] is also a type. Is there language that exists to differentiate the two?
What is A?
What is F[A]?
What is F?
Dunno about in Scala, but in Haskell, the Report does distinguish between two syntactic categories: "types" and "constructors". Constructors are just those types which are single atoms, beginning with an upper case letter, and created by data and newtype declarations. e.g.
data Foo a = Bar
creates a new type constructor Foo (and a new data constructor Bar), and types can be formed by applying Foo to another type. Of course, constructors need not be of higher kind; data Baz = Quux also declares a type constructor named Baz which is not permitted to be applied to any other types.
(But beware: it is common to use "type constructor" to mean "any type-level expression with an arrow kind", so if you are doing some technical writing, you should include some text in your introduction clarifying which of these two meanings you intend to use in the rest of the document.)
So, in your example, we could say Map is a constructor, Char is a constructor, Int is a constructor, Map Char is a type, and Map Char Int is a type.
As far as I know, there is no common shorthand term for any of these categories: "a type which is definitely not a constructor", "a type of kind *", "a type which is definitely not of kind *". For types which are allowed to be applied to another type, there is the term "higher-kinded type" -- e.g. Map and Map Char are both higher-kinded types.
I would propose to just call F[A] application of a type constructor F of kind * -> * to the argument A of kind *. "Type constructor" comes from the specification, whereas "application" comes from the basic lambda calculus, as explained below.
Recall that the formalism of higher-kinded types with all the type constructors is essentially just an extension of a simply typed lambda calculus over a single type *.
That means that you have the following rules for forming kinds:
* is a kind
if a, b are kinds, then a -> b is a kind
You can form terms as follows:
Predefined constants with fixed kind are terms
Variables are terms
If f and a are terms, then the application f a is a term
If x is a variable name, and y is a term, then the abstraction \x.y is a term
You can check whether a (type-valued) term is well-kinded with rules that look somewhat like this:
Predefined constant c of kind k (vacuously) has kind k, regardless of context
If context Gamma contains mapping of a variable v to kind k, then in Gamma we can infer that v is a well-kinded expression of kind k.
If in context Gamma we can infer that f has kind a -> b and x has kind a, then the application f x has kind b.
If in context Gamma, x: a we can infer that y has kind b, then in Gamma we can infer that \x.y has kind a -> b.
I don't see any reason to invent any new vocabulary, so I would just use "application".
An aside: you can actually write down the above basic kind-inference algorithm really quickly.
sealed trait Term
case class Apply(func: Term, arg: Term) extends Term
case class Lam(preferred: String, dom: Type, body: Term) extends Term
case class BoundVar(deBruijnIdx: Int) extends Term
case class FreeVar(name: String) extends Term
sealed trait Type
case object * extends Type
case class Func(dom: Type, cod: Type) extends Type {
override def toString = s"($dom -> $cod)"
}
import util.{Either, Left, Right}
case class Ctx(globalConstants: Map[String, Type], stack: List[Type]) {
def push(tp: Type): Ctx = Ctx(globalConstants, tp :: stack)
def pop: Ctx = Ctx(globalConstants, stack.tail)
}
object Ctx {
def empty = Ctx(Map.empty, List.empty)
def emptyWithGlobals(keys: (String, Type)*) = Ctx(keys.toMap, Nil)
}
def tinf(t: Term, ctx: Ctx = Ctx.empty): Either[String, Type] = t match {
case FreeVar(v) =>
ctx.globalConstants.get(v).map(Right(_)).getOrElse(Left("Undefined: " + v))
case BoundVar(d) => Right(ctx.stack(d))
case Apply(f, x) =>
for {
tf <- tinf(f, ctx)
tx <- tinf(x, ctx)
res <- tf match {
case Func(a, b) =>
if (tx == a) Right(b)
else Left(s"Type mismatch: cannot apply `$a` to `$b`")
case sthElse => Left(s"Not applicable: $sthElse")
}
} yield res
case Lam(_, tp, b) =>
for {
tb <- tinf(b, ctx.push(tp))
} yield Func(tp, tb)
}
for {
example <- List(
Lam("x", *, BoundVar(0)),
Lam("x", *, Lam("y", Func(*, *), Apply(BoundVar(0), BoundVar(1))))
)
} println(example + " : " + tinf(example))
and it will happily infer that type-lambdas
\(x:*).x
\(x:*).\y(* -> *). y x
have the kinds
(* -> *)
(* -> ((* -> *) -> *))
respectively.
The technical terms, as mentioned in the comments, are 'type', 'some other type', and a 'type constructor'.
Consider:
data A = A
-- ^ ^--- The Data Constructor
-- -- The type
data F x = SomeDataConstructorForF x
-- ^ ^ ^-- Data Constr ^-- Field
-- | --- Type Variable
-- - Type Constructor
val :: A
val = A
-- A value of type 'A'
val2 :: F [A]
val2 = SomeDataConstructorForF []
-- A value of some other type, F [A].
-- No special term exists for types built through application
-- of one or more type constructor afaik

Strange type inference behavior

I'm trying to understand why purescript is unable to properly infer type for map parameter in this simple code:
maybeInc :: String -> StateT (Maybe Int) Identity Unit
maybeInc "a" = modify $ map (1 +)
maybeInc _ = return unit
Here is my error message:
No type class instance was found for
Control.Monad.State.Class.MonadState (_0 Int)
(StateT (Maybe Int) Identity)
The instance head contains unknown type variables. Consider adding a type annotation.
However, it works if I specify the type manually:
maybeInc "a" = modify $ \(m :: Maybe Int) -> map (1 +) m
Why it doesn't want to infer this type automatically even it's already provided in function signature?
The current compiler has no way of modeling functional dependencies, which are used in Haskell and the mtl library to capture the relationship between the two type arguments in MonadState.
This means that the compiler can't figure out that the two state types have to be the same (that is, if we find an instance of MonadState for StateT (Maybe Int) Identity, the state type is forced to be Maybe Int).
For now, one solution is to add a type annotation:
maybeInc :: String -> StateT (Maybe Int) Identity Unit
maybeInc "a" = modify modifier
where
modifier :: Maybe Int -> Maybe Int
modifier = map (1 +)
maybeInc _ = return unit

How do type classes work in Haskell?

I am really confused about classes in haskell. If I had the code:
class GetResult n where res :: n -> Int
class (GetResult n) => Model n where
starting :: Int -> [Int] -> n
starting i j = .....
test :: n -> n
test n = ......
What type is n? What type would starting output and test take as input?
Your confusion might be caused by the fact that type classes in Haskell have nothing to do with classes in OO. Most importantly type classes don't describe objects, they describe types.
A type class describes a set of methods. You can implement those methods for a given type to make that type an instance of the class. So your type class definition of GetResult can be read as "A type n can be made an instance of GetResult by implementing the method res of type n -> Int". So n is simply the type that wants to become an instance of GetResult.
As an example if you wanted to make Int an instance of GetResult, you could use the following instance declaration:
instance GetResult Int where
res :: Int -> Int
res i = i
In this case n would be Int.
n is a type variable, not any particular type. Particular types can be made instances of GetResult and Model, and each instance will "fill in the blanks" in the types of the functions defined in the class.
So the full type of starting is (you can get this from ghci with :t starting):
starting :: Model n => Int -> [Int] -> n
You can read this as "for any type which is an instance of Model, starting takes an Int and a [Int] and returns a value of that type". Likewise test takes any type which is an instance of Model and returns a value of the same type.
At any particular call of starting, the type returned will be determined by the context; it will return a value of whatever type its return value is used as in that context (assuming a suitable instance exists).

Impredicative types vs. plain old subtyping

A friend of mine posed a seemingly innocuous Scala language question last week that I didn't have a good answer to: whether there's an easy way to declare a collection of things belonging to some common typeclass. Of course there's no first-class notion of "typeclass" in Scala, so we have to think of this in terms of traits and context bounds (i.e. implicits).
Concretely, given some trait T[_] representing a typeclass, and types A, B and C, with corresponding implicits in scope T[A], T[B] and T[C], we want to declare something like a List[T[a] forAll { type a }], into which we can throw instances of A, B and C with impunity. This of course doesn't exist in Scala; a question last year discusses this in more depth.
The natural follow-up question is "how does Haskell do it?" Well, GHC in particular has a type system extension called impredicative polymorphism, described in the "Boxy Types" paper. In brief, given a typeclass T one can legally construct a list [forall a. T a => a]. Given a declaration of this form, the compiler does some dictionary-passing magic that lets us retain the typeclass instances corresponding to the types of each value in the list at runtime.
Thing is, "dictionary-passing magic" sounds a lot like "vtables." In an object-oriented language like Scala, subtyping is a much more simple, natural mechanism than the "Boxy Types" approach. If our A, B and C all extend trait T, then we can simply declare List[T] and be happy. Likewise, as Miles notes in a comment below, if they all extend traits T1, T2 and T3 then I can use List[T1 with T2 with T3] as an equivalent to the impredicative Haskell [forall a. (T1 a, T2 a, T3 a) => a].
However, the main, well-known disadvantage with subtyping compared to typeclasses is tight coupling: my A, B and C types have to have their T behavior baked in. Let's assume this is a major dealbreaker, and I can't use subtyping. So the middle ground in Scala is pimps^H^H^H^H^Himplicit conversions: given some A => T, B => T and C => T in implicit scope, I can again quite happily populate a List[T] with my A, B and C values...
... Until we want List[T1 with T2 with T3]. At that point, even if we have implicit conversions A => T1, A => T2 and A => T3, we can't put an A into the list. We could restructure our implicit conversions to literally provide A => T1 with T2 with T3, but I've never seen anybody do that before, and it seems like yet another form of tight coupling.
Okay, so my question finally is, I suppose, a combination of a couple questions that were previously asked here: "why avoid subtyping?" and "advantages of subtyping over typeclasses" ... is there some unifying theory that says impredicative polymorphism and subtype polymorphism are one and the same? Are implicit conversions somehow the secret love-child of the two? And can somebody articulate a good, clean pattern for expressing multiple bounds (as in the last example above) in Scala?
You're confusing impredicative types with existential types. Impredicative types allow you to put polymorphic values in a data structure, not arbitrary concrete ones. In other words [forall a. Num a => a] means that you have a list where each element works as any numeric type, so you can't put e.g. Int and Double in a list of type [forall a. Num a => a], but you can put something like 0 :: Num a => a in it. Impredicative types is not what you want here.
What you want is existential types, i.e. [exists a. Num a => a] (not real Haskell syntax), which says that each element is some unknown numeric type. To write this in Haskell, however, we need to introduce a wrapper data type:
data SomeNumber = forall a. Num a => SomeNumber a
Note the change from exists to forall. That's because we're describing the constructor. We can put any numeric type in, but then the type system "forgets" which type it was. Once we take it back out (by pattern matching), all we know is that it's some numeric type. What's happening under the hood, is that the SomeNumber type contains a hidden field which stores the type class dictionary (aka. vtable/implicit), which is why we need the wrapper type.
Now we can use the type [SomeNumber] for a list of arbitrary numbers, but we need to wrap each number on the way in, e.g. [SomeNumber (3.14 :: Double), SomeNumber (42 :: Int)]. The correct dictionary for each type is looked up and stored in the hidden field automatically at the point where we wrap each number.
The combination of existential types and type classes is in some ways similar to subtyping, since the main difference between type classes and interfaces is that with type classes the vtable travels separately from the objects, and existential types packages objects and vtables back together again.
However, unlike with traditional subtyping, you're not forced to pair them one to one, so we can write things like this which packages one vtable with two values of the same type.
data TwoNumbers = forall a. Num a => TwoNumbers a a
f :: TwoNumbers -> TwoNumbers
f (TwoNumbers x y) = TwoNumbers (x+y) (x*y)
list1 = map f [TwoNumbers (42 :: Int) 7, TwoNumbers (3.14 :: Double) 9]
-- ==> [TwoNumbers (49 :: Int) 294, TwoNumbers (12.14 :: Double) 28.26]
or even fancier things. Once we pattern match on the wrapper, we're back in the land of type classes. Although we don't know which type x and y are, we know that they're the same, and we have the correct dictionary available to perform numeric operations on them.
Everything above works similarly with multiple type classes. The compiler will simply generate hidden fields in the wrapper type for each vtable and bring them all into scope when we pattern match.
data SomeBoundedNumber = forall a. (Bounded a, Num a) => SBN a
g :: SomeBoundedNumber -> SomeBoundedNumber
g (SBN n) = SBN (maxBound - n)
list2 = map g [SBN (42 :: Int32), SBN (42 :: Int64)]
-- ==> [SBN (2147483605 :: Int32), SBN (9223372036854775765 :: Int64)]
As I'm very much a beginner when it comes to Scala, I'm not sure I can help with the final part of your question, but I hope this has at least cleared up some of the confusion and given you some ideas on how to proceed.
#hammar's answer is perfectly right. Here is the scala way of doint it. For the example i'll take Show as the type class and the values i and d to pack in a list :
// The type class
trait Show[A] {
def show(a : A) : String
}
// Syntactic sugar for Show
implicit final class ShowOps[A](val self : A)(implicit A : Show[A]) {
def show = A.show(self)
}
implicit val intShow = new Show[Int] {
def show(i : Int) = "Show of int " + i.toString
}
implicit val stringShow = new Show[String] {
def show(s : String) = "Show of String " + s
}
val i : Int = 5
val s : String = "abc"
What we want is to be able run the following code
val list = List(i, s)
for (e <- list) yield e.show
Building the list is easy but the list won't "remember" the exact type of each of its elements. Instead it will upcast each element to a common super type T. The more precise super super type between String and Int being Any, the type of the list is List[Any].
The problem is: what to forget and what to remember? We want to forget the exact type of the elements BUT we want to remember that they are all instances of Show. The following class does exactly that
abstract class Ex[TC[_]] {
type t
val value : t
implicit val instance : TC[t]
}
implicit def ex[TC[_], A](a : A)(implicit A : TC[A]) = new Ex[TC] {
type t = A
val value = a
val instance = A
}
This is an encoding of the existential :
val ex_i : Ex[Show] = ex[Show, Int](i)
val ex_s : Ex[Show] = ex[Show, String](s)
It pack a value with the corresponding type class instance.
Finally we can add an instance for Ex[Show]
implicit val exShow = new Show[Ex[Show]] {
def show(e : Ex[Show]) : String = {
import e._
e.value.show
}
}
The import e._ is required to bring the instance into scope. Thanks to the magic of implicits:
val list = List[Ex[Show]](i , s)
for (e <- list) yield e.show
which is very close to the expected code.