Remove phantom type variable - haskell

Suppose i have some type like:
newtype Foo a b = Foo { getFoo :: SomeStructure b }
I.e. a is a phantom type used only for compile-time checks.
However, I don't want to use the phantom type everywhere. It's not universally useful in my code. So I would like to do something like:
type FooUnrestricted b = Foo Anything b
What should I use in place of Anything? Do I need some language extensions?
Edit: I realized I could simply use () and it would answer my question. But the actual point is that I have functions that place constraints on a and I would like them to be always satisfied.

One option is to use an existential type:
data UnrestrictedFoo b where
Unrestricted :: Foo a b -> UnrestrictedFoo b
In some other contexts, it may make sense to use a rank 2 type instead.
newtype UnrestrictedFoo b = UnrestrictedFoo (forall a . Foo a b)

You're probably looking for undefined at type level to make a stub for types. This was already discussed here:
Undefined at the type level
So you can define your own data type and make instances for it of any type classes you use. If you want to lower number of instances you need to implement, you can use some standard data types like Void or even Proxy (). The latter is better because it has more instances.
http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Void.html
http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Proxy.html

I agree that () is the best type to use here, as it conveys that you don't care about the type, but if you want it to satisfy your code constraints, you could newtype it and derive the needed instances trivially when you need them.

Related

Contrained type familly

I have the following type family in haskell :
type family Foo (a :: Bar) :: * where
followed by a bunch of equality. I want to put a constraint on the kind return to ensure they're all instance of a typeclass. How can i do that ?
Seems like you're looking for
class (YourConstraint (Foo a)) => Fooish (a :: Bar) where
type Foo a :: Type
As Carl noted, this is somewhat analogous to the old data declaration style with
data C a => D a = D ...
which is widely considered a bad idea because it's not possible to use the constraint, all it accomplishes is preventing to build values that don't obey the constraint.
But unlike those data declarations, a constraint to an associated type family is useful IMO, because there's an easy way to get at the constrait whenever it's needed: you just need to mention Fooish.
In Haskell, it's better not to do that. (See also the desire to put constraints on type variables in data declarations.) You should put constraints where they're actually going to be used. That will still get called out during type checking if it's missing when it's needed, but it will allow things that don't need it to be more flexible.

Isomorphism in newtype

I'm trying to understand State newtype and I'm struggling with this explanation of the isomorphism in a book:
Newtypes must have the same underlying representation as the type they wrap, as the newtype wrapper disappears at compile time. So the function contained in the newtype must be isomorphic to the type it wraps. That is, there must be a way to go from the newtype to the thing it wraps and back again without losing information.
What does it mean applied to State newtype?
newtype State s a = State { runState :: s -> (a, s) }
That explanation "there must be a way to go from the newtype to the thing it wraps and back again" isn't clear.
Also, can you please say, where there is an isomorphism in this examples, where is not and why.
type Iso a b = (a -> b, b -> a)
newtype Sum a = Sum { getSum :: a }
sumIsIsomorphicWithItsContents :: Iso a (Sum a)
sumIsIsomorphicWithItsContents = (Sum, getSum)
(a -> Maybe b, b -> Maybe a)
[a] -> a, a -> [a]
The statement you quote makes no mention of State specifically. It is purely a statement about newtypes. It is a little misleading in referring to "the function contained in the newtype" because there is no requirement for the type wrapped by a newtype to be a function type - although this is the case for State and many other commonly used types defined by newtype.
The key thing for a newtype in general is exactly as it says: it has to simply wrap another type in a way that makes it trivial to go from the wrapped type to the wrapping one, and vice versa, with no loss of information - this is what it means for two types to be isomorphic, and also what makes it completely safe for the two types to have identical runtime representations.
It's easy to demonstrate typical data declarations that could not possibly fulfil this. For example take any type with 2 constructors, such as Either:
data Either a b = Left a | Right b
It's obvious that this is not isomorphic to either of its constituent types. For example, the Left constructor embeds a inside Either a b, but you can't get any of the Right values this way.
And even with a single constructor, if it takes more than one argument - such as the tuple constructor (,) - then again, you can embed either of the constituent types (given an arbitrary value of the other type) but you can't possibly get every value.
This is why the newtype keyword is only allowed for types with a single constructor which takes a single argument. This always provides an isomorphism, because given newtype Foo a = Foo a, then Foo constructor and the function \Foo a -> a are trivially inverses of each other. And this works the same for more complicated examples where the type constructor takes more type arguments, and/or where the wrapped type is more complex.
Such is exactly the case with State:
newtype State s a = State {runState :: s -> (a, s)}
The functions State and runState respectively wrap and unwrap the underlying type (which in this case is a function), and clearly are inverse to each other - therefore they provide an isomorphism.
Note finally that there is nothing special here about the use of record syntax in the definition - although it's very common in such cases in order to have an already-named "unwrapping" function. Other than this small convenience there is no difference from a newtype defined without record syntax.
To step back a little: newtype declarations are very similar to data declarations with a single constructor and a single argument - the difference is mainly in performance, as the keyword tells the compiler that the two types are equivalent so that there is no runtime overhead of conversion between the two types, which there otherwise would be. (There is also a difference with regard to laziness but I won't mention that, except here for completeness.) As for why do this rather than just use the underlying type - that's to provide extra type safety (there are 2 different types here for the compiler even though they're the same at runtime), and also allows typeclass instances to be specified without attaching those to the underlying type. Sum and Product are great examples here, as they provide Monoid instances for numeric types, based on addition and multiplication respectively, without giving either the undeserved distinction of being "the" Monoid instance for the underlying type.
And something similar is at work with State - when we use this type we signal explicitly that we're using it to represent state manipulation, which wouldn't be the case if we were just working with ordinary functions that happen to return a pair.

Is it possible to only expose the typeclass interface of a return value?

In the following code all that I ever do with the return value of foo is use its Show interface
foo :: String
foo = "asdf"
main = do
print foo
Is there a way to modify the type signature offoo to enforce this, forbidding people from treating the string as a list of characters and only letting them access it though the abstract type class interface? I think it might be possible with existential types but I have no idea how.
The reason I want to do this is because in the HDBC database library all the functionality is available as methods of a IConnection type class. I am writing the function that creates the database connection and I want to know if its possible to have its return type reflect the abstract interface instead of returning a concrete Sqlite3 Connection.
Now that I searched a bit I see that there is a ConnWrapper datatype available but I still can't understand how this all fits together. Is returning a ConnWrapper the only way to go?
It's indeed possible with existential types, but it's quite possibly a bad idea.
The way you would do it with an existential type is ConnWrapper, like you said:
data ConnWrapper = forall conn. IConnection conn => ConnWrapper conn
That type is relatively straightforward: It's an IConnection dictionary together with a value of a type compatible with it. If x :: conn, and conn is an instance of IConnection, then ConnWrapper x :: ConnWrapper. Given y :: ConnWrapper, you know nothing about its value's type other than that it's an instance of IConnection. So you can say case y of ConnWrapper z -> disconnect z, but you can't say case y of ConnWrapper z -> z -- there's no Haskell type you can give to that.
(ConnWrapper is also an instance of IConnection directly, and since the class is pretty simple, that means you pretty much never need to pattern-match on ConnWrapper directly. You can just use disconnect y and so on.)
If you were making the API, I'd strongly suggest reconsidering along the lines of the post I linked above, or at least understanding that approach. Many uses of ExistentialTypes in Haskell are actually more complicated than a non-existential approach. For example, you should see why data Foo = forall a. Show a => Foo a is (almost) equivalent to String. It looks like the HDBC may be intended to be used this way, though...

Lambda for type expressions in Haskell?

Does Haskell, or a specific compiler, have anything like type-level lambdas (if that's even a term)?
To elaborate, say I have a parametrized type Foo a b and want Foo _ b to be an instance of, say, Functor. Is there any mechanism that would let me do something akin to
instance Functor (\a -> Foo a b) where
...
?
While sclv answered your direct question, I'll add as an aside that there's more than one possible meaning for "type-level lambda". Haskell has a variety of type operators but none really behave as proper lambdas:
Type constructors: Abstract type operators that introduce new types. Given a type A and a type constructor F, the function application F A is also a type but carries no further (type level) information than "this is F applied to A".
Polymorphic types: A type like a -> b -> a implicitly means forall a b. a -> b -> a. The forall binds the type variables within its scope, thus behaving somewhat like a lambda. If memory serves me this is roughly the "capital lambda" in System F.
Type synonyms: A limited form of type operators that must be fully applied, and can produce only base types and type constructors.
Type classes: Essentially functions from types/type constructors to values, with the ability to inspect the type argument (i.e., by pattern matching on type constructors in roughly the same way that regular functions pattern match on data constructors) and serving to define a membership predicate on types. These behave more like a regular function in some ways, but are very limited: type classes aren't first-class entities that can be manipulated, and they operate on types only as input (not output) and values only as output (definitely not input).
Functional dependencies: Along with some other extensions, these allow type classes to implicitly produce types as results as well, which can then be used as the parameters to other type classes. Still very limited, e.g. by being unable to take other type classes as arguments.
Type families: An alternate approach to what functional dependencies do; they allow functions on types to be defined in a manner that looks much closer to regular value-level functions. The usual restrictions still apply, however.
Other extensions relax some of the restrictions mentioned, or provide partial workarounds (see also: Oleg's type hackery). However, pretty much the one thing you can't do anywhere in any way is exactly what you were asking about, namely introduce new a binding scope with an anonymous function abstraction.
From TypeCompose:
newtype Flip (~>) b a = Flip { unFlip :: a ~> b }
http://hackage.haskell.org/packages/archive/TypeCompose/0.6.3/doc/html/Control-Compose.html#t:Flip
Also, if something is a Functor in two arguments, you can make it a bifunctor:
http://hackage.haskell.org/packages/archive/category-extras/0.44.4/doc/html/Control-Bifunctor.html
(or, in a later category-extras, a more general version: http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/Control-Functor.html#t:Bifunctor)
I don't like the idea of answering my own question, but apparently, according to several people on #haskell on Freenode, Haskell doesn't have type-level lambdas.
EHC (and perhaps also its successor, UHC) has type-level lambdas, but they are undocumented and not as powerful as in a dependently-typed language. I recommend you use a dependently-typed language such as Agda (similar to Haskell) or Coq (different, but still pure functional at its core, and can be interpreted and compiled either lazily or strictly!) But I'm biased towards such languages, and this is probably 100x overkill for what you are asking for here!
The closest I know of to get a type lambda is by defining a type synonym. In your example,
data Foo a b = Foo a b
type FooR a b = Foo b a
instance Functor (FooR Int) where
...
But even with -XTypeSynonymInstances -XFlexibleInstances this doesn't work; GHC expects the type syn to be fully applied in the instance head. There may be some way to arrange it with type families.
Yeah, what Gabe said, which is somewhat answered by type families:
http://www.haskell.org/haskellwiki/GHC/Type_families
Depending on the situation, you could replace your original type definition with a "flipped" version, and then make a type synonym for the "correct" version.
From
data X a b = Y a b
instance Functor (\a -> X a b) where ...
to
data XFlip b a = Y a b -- Use me for instance decalarations
type X a b = XFlip b a -- Use me for everything else
instance Functor XFlip where ...

Trying to understand Haskell's => vs defining the types

In Haskell, why would you define a function with a type constraint:
ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
Rather than defining it so it's type was:
ghci> :t (==)
(==) :: Eq -> Eq -> Bool
You wouldn't do the second version because you'd get a compile error. Eq is not a type, it's a typeclass. You can't use a typeclass in places where a type is required.
If you did define your own type MyEq and then define a function == with the type MyEq -> MyEq -> Bool, the expression "hello" == "hello" would be invalid because "hello" is a value of type String and not of type MyEq. Since there is no subtyping in haskell a value couldn't be of type String and of type MyEq at the same time.
So if you want to define a function that can accept values of different types which meet certain conditions, you need type classes.
In Haskell, a "type" can only have a single specific set of possible values
that does not overlap with any other type.
There is no such thing as one type being "a different kind of"
or "a subtype of" another type.
When we want polymorphism, i.e., functions that can apply to more than
one type, we can specify that by using a type variable in the type
signature of the function.
But a type variable can refer to any
type at all. We don't always know how to define our function
for absolutely every type. For example, the (>)
function only makes sense for types whose elements are
comparable. The compiler will reject
a function whose type signature is too general, in order
to help us avoid writing gibberish.
In your example, Eq is not a type. It is a
typeclass - a name for a set of types. We declare
typeclass names using the class keyword, and
add types into the class using the instance
keyword. The purpose of a typeclass is to be used in a
constraint to limit
the scope of a type variable.
The Haskell approach to types and polymorphism is based on the
"Hindley-Milner type system". It is an extremely precise
yet very expressive way of describing data that makes it
easier to give the compiler a huge amount of intelligence
about the types in your program. That intelligence helps
the compiler to infer types automatically, to give you
a lot of help in getting your program correct, and to optimize
the compiled result, among other benefits.
But be careful - it is very different than the way types are
used in OOP, which may be what you are used to. There is usually no
direct translation between an OO program and a Haskell program.
You have to think about the task in a different way right from
the start. Be especially careful not to confuse Haskell's concepts
of "class" and "instance" with the completely different way those
words are used in OOP.

Resources