Using a type of a parameterized data type in a Haskell function - haskell

Let's say I have some algebraic data type in Haskell:
data Foo a = ...
I'd like to have a function that could "extract" this type a and do something with it, assuming it satisfies certain conditions. Specifically, I need something like:
fun :: Bounded a => Foo a -> a
with intended usage as follows:
fun foo = maxBound :: a
Of course this notation is incorrect in Haskell, but I think my intentions are clear. Is it possible to do something like this?

You don't need anything, it just works.
fun :: Bounded a => Foo a -> a
fun _ = maxBound
The compiler knows that the result of fun would be an a and therefore will call the correct maxBound.

Related

Haskell RankNTypes - restriction of function domain

I don't understand why it is so, referring to : What is the purpose of Rank2Types? -> #dfeuer explanation:
... Requiring an argument to be polymorphic doesn't just allow it to be used with multiple types; it also restricts what that function can do with its argument(s) and how it can produce its result
...
f :: (forall a . [a] -> a) -> IO ()
... In fact, no function returning an element not in the list it is given will typecheck
In any explanation of rank-N types I haven't see this effect (or benefit) described, much of the time it was the story about letting the callee choose the type etc... that is clear for me and easy to grasp but I don't see by which virtue (only of extending the rank) we can control/restrict the function domain (and co-domain)...
if somebody could give a deeper insigth of the rankN mechanism involved here. thx
Just think about it in terms of polymorphic functions you declare on the top-level. A function with the signature like
foo :: [Int] -> Int
has lots of possible implementations like
foo = sum
foo = length
foo _ = 39
but none of these are legal if the signature were
foo :: [a] -> a
because then you can't give an integer as the result – you must provide a result of whatever type the caller demands. So the implementation is much more restricted: the result must come from the input list, because that's the only place you know the elements have type a no matter what the caller actually instantiates this to. Only something like
foo = head
will work then.
Your RankN signature requires its argument to be such a polymorphic function, i.e. the argument can't be a [Int] -> Int but only the more restrictive [a] -> a.

Getting/returning the type of a function

Is there any way to get and return the type of a function in Haskell?
Suppose that I have this kind of function:
foo :: Int -> Int -> String
foo a b = (show a ++ show b ++ "hello")
From the code above, what I actually want is to get this kind of tuple as a return value of function:
> getTypeTuple foo
(Int, Int, String)
As far as I know, the type itself cannot be treated as a part of expressions, so I guess it wouldn't be possible to have this kind of feature at the runtime in Haskell. (Static type!!)
Then will there be any similar alternative, or preprocessor feature in Haskell?
Edit: I think what I really want is the Haskell implementation of :t command in GHCi.
You can use Template Haskell to do your metaprogramming, and that allows you to get the type of a function. See this question for how to get the type.

Why `Just String` will be wrong in Haskell

Hi I have a trivial but exhausting question during learning myself the Parameterized Types topic in Haskell. Here is my question:
Look this is the definition of Maybe:
data Maybe a = Just a | Nothing
And we use this like:
Just "hello world"
Just 100
But why can't Just take a type variable?
For example:
Just String
Just Int
I know this problem is quite fool, but I still can't figure it out...
Well, first note that String and Int aren't type variables, but types (type constants, if you will). But that doesn't really matter for the purpose of your question.
What matters is the destinction between Haskells type language and value language. These are generally kept apart. String and Int and Maybe live in the type language, while "hello world" and 100 and Just and Nothing live in the value language. Each knows nothing about the other side. Only, the compiler knows "this discription of a value belongs to that type", but really types exist only at compile-time and values exist only at runtime.
Two things that are a bit confusing:
It's allowed to have names that exist both in the type- and value language. Best-known are () and mere synonym-type like
newtype Endo a = Endo { runEndo :: a -> a }
but really these are two seperate entities: the type constructor Endo :: *->* (see below for these * thingies) and the value constructor Endo :: (a->a) -> Endo a. They just happen to share the same name, but in completely different scopes – much like when you declare both addTwo x = x + 2 and greet x = "Hello "++x, where both uses of the x symbol have nothing to do with each other.
The data syntax seems to intermingle types and values. Everywhere else, types and values must always be separated by a ::, most typically in signatures
"hello world" :: String
100 :: Int
Just :: Int -> Maybe Int
{-hence-}Just 100 :: Maybe Int
Nothing :: Maybe Int
foo :: (Num a, Ord a) => a -> Maybe a -- this really means `forall a . (Num a, Ord a) => a -> Maybe a
foo n | n <= 0 = Nothing
| otherwise = Just $ n - 1
and indeed that syntax can be used to define data in more distinctive way too, if you enable -XGADTs:
data Maybe a where
Just :: a -> Maybe a
Nothing :: Maybe a
Now we have the :: again as a clear distinction between value-level (left) and type-level.
You can actually take it up one more level: the above declaration can also be written
data Maybe :: * -> * where
Just :: a -> Maybe a
Nothing :: Maybe a
Here Maybe :: * -> * means, "Maybe is a type-level thing that has kind * -> *", i.e. it takes a type-level argument of kind * (such as Int) and returns another type-level thing of kind * (here, Maybe Int). Kinds are to types as types are to values.
You can certainly declare data Maybe a = Just String | Nothing, and you can declare data Maybe a = Just Int | Nothing, but only one of them at a time. Using a type variable permits to declare in what way the type of the contents of the constructed values change with the value of the type variable. So data Maybe a = Just a | Nothing tells us that the contents "inside" Just is exactly of the type passed to Maybe. That way Maybe String means that "inside" Just there is a value of type String, and Maybe Int means that "inside" Just there is a value of type Int.

learning type of argument in function

How can I learn type of argument at function in Haskell ? In python, we have type ( ) function.
Ex:
in func;
if type ( a ) == Int
do <something>
But, I don't know how I can manage that wish in Haskell ?
You don't need this since Haskell is statically typed and all types are known at compile time. In case of polymorphic functions like length :: [a] -> Int (Calculate the length of a list of elements of type a), there is no way to find out about the type of the argument, since you specified with the type that any argument type fits.
You have http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Typeable.html
However compared to dynamic languages it is very very rare that you need to use such means, and as beginner you shouldn't even try to use it, as you're almost certainly doing it wrong, even if you are sure that you need it. You should embrace Haskell's battle cry "Follow the type!" and express your thoughts using the type system instead of trying to subvert it.
If you are trying to do type-directed dispatch, then you probably want a typeclass.
data Bar = ...
class Foo a where
foo :: a -> Bar
instance Foo Int where
foo = ...
func :: Foo a => a -> ...
func x ... = ... foo x ...
Notice how the type signature demands that x is an instance of the Foo class. That means we can call foo on x and the type-directed dispatch will be done for us, in a type-safe way. If you write code that tries to call foo on something that is not an instance of Foo, then it will be a type error.
The reason you are not allowed to perform your own type-directed dispatch in Haskell is because that would break some important guarantees given to you by the type system. We would have to say goodbye to our theorems for free.

Are there "type-level combinators"? Will they exist in some future?

Much of what makes haskell really nice to use in my opinion are combinators such as (.), flip, $ <*> and etc. It feels almost like I can create new syntax when I need to.
Some time ago I was doing something where it would be tremendously convenient if I could "flip" a type constructor. Suppose I have some type constructor:
m :: * -> * -> *
and that I have a class MyClass that needs a type with a type constructor with kind * -> *. Naturally I would choose to code the type in such a way that I can do:
instance MyClass (m a)
But suppose I can't change that code, and suppose that what really fits into MyClass is something like
type w b = m b a
instance MyClass w where
...
and then I'd have to activate XTypeSynonymInstances. Is there some way to create a "type level combinator" Flip such that I can just do:
instance MyClass (Flip m a) where
...
?? Or other type level generalisations of common operators we use in haskell? Is this even useful or am I just rambling?
Edit:
I could do something like:
newtype Flip m a b = Flip (m b a)
newtype Dot m w a = Dot m (w a)
...
But then I'd have to use the data constructors Flip, Dot, ... around for pattern matching and etc. Is it worth it?
Your question makes sense, but the answer is: no, it's not currently possible.
The problem is that (in GHC Haskell's type system) you can't have lambdas at the type level. For anything you might try that looks like it could emulate or achieve the effect of a type level lambda, you will discover that it doesn't work. (I know, because I did.)
What you can do is declare your Flip newtypes, and then write instances of the classes you want for them, painfully with the wrapping and the unwrapping (by the way: use record syntax), and then clients of the classes can use the newtypes in type signatures and not have to worry about the details.
I'm not a type theorist and I don't know the details of why exactly we can't have type level lambdas. I think it was something to do with type inference becoming impossible, but again, I don't really know.
You can do the following, but I don't think its actually very useful, since you still can't really partially apply it:
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
module Main where
class TFlip a where
type FlipT a
instance TFlip (f a b) where
type FlipT (f a b) = f b a
-- *Main> :t (undefined :: FlipT (Either String Int))
-- (undefined :: FlipT (Either String Int)) :: Either Int [Char]
Also see this previous discussion: Lambda for type expressions in Haskell?
I'm writing answer here just for clarifying things and to tell about achievements in the last years. There're a lot of features in Haskell and now you can write some operators in type. Using $ you can write something like this:
foo :: Int -> Either String $ Maybe $ Maybe Int
to avoid parenthesis instead of good old
foo :: Int -> Either String (Maybe (Maybe Int))

Resources