Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a type 'Any' in haskell?

Tags:

haskell

Say, I want to define a record Attribute like this:

data Attribute = Attribute {name :: String, value :: Any}

This is not valid haskell code of course. But is there a type 'Any' which basically say any type will do? Or is to use type variable the only way?

data Attribute a = Attribute {name :: String, value :: a}

like image 657
edwardw Avatar asked Jun 25 '11 17:06

edwardw


People also ask

What are types in Haskell?

In Haskell, every statement is considered as a mathematical expression and the category of this expression is called as a Type. You can say that "Type" is the data type of the expression used at compile time. To learn more about the Type, we will use the ":t" command.

Can Haskell lists have different types?

Haskell also incorporates polymorphic types---types that are universally quantified in some way over all types. Polymorphic type expressions essentially describe families of types. For example, (forall a)[a] is the family of types consisting of, for every type a, the type of lists of a.

How do you declare types in Haskell?

Haskell has three basic ways to declare a new type: The data declaration, which defines new data types. The type declaration for type synonyms, that is, alternative names for existing types. The newtype declaration, which defines new data types equivalent to existing ones.

How does Haskell infer types?

Types are infered using a process generally called unification. Haskell belongs to the Hindley-Milner family, which is the unification algorithm it uses to determine the type of an expression. If unification fails, then the expression is a type error.


2 Answers

Generally speaking, Any types aren't very useful. Consider: If you make a polymorphic list that can hold anything, what can you do with the types in the list? The answer, of course, is nothing - you have no guarantee that there is any operation common to these elements.

What one will typically do is either:

  1. Use GADTs to make a list that can contain elements of a specific typeclass, as in:

    data FooWrap where
        FooWrap :: Foo a => a -> FooWrap
    type FooList = [FooWrap]
    

    With this approach, you don't know the concrete type of the elements, but you know they can be manipulated using elements of the Foo typeclass.

  2. Create a type to switch between specific concrete types contained in the list:

    data FooElem = ElemFoo Foo | ElemBar Bar
    type FooList = [FooElem]
    

    This can be combined with approach 1 to create a list that can hold elements that are of one of a fixed set of typeclasses.

  3. In some cases, it can be helpful to build a list of manipulation functions:

    type FooList = [Int -> IO ()]
    

    This is useful for things like event notification systems. At the time of adding an element to the list, you bind it up in a function that performs whatever manipulation you'll later want to do.

  4. Use Data.Dynamic (not recommended!) as a cheat. However, this provides no guarantee that a specific element can be manipulated at all, and so the above approaches should be preferred.

like image 82
bdonlan Avatar answered Oct 19 '22 05:10

bdonlan


Adding to bdonlan's answer: Instead of GADTs, you can also use existential types:

{-# LANGUAGE ExistentialQuantification #-}

class Foo a where
  foo :: a -> a

data AnyFoo = forall a. Foo a => AnyFoo a

instance Foo AnyFoo where
  foo (AnyFoo a) = AnyFoo $ foo a

mapFoo :: [AnyFoo] -> [AnyFoo]
mapFoo = map foo

This is basically equivalent to bdonlan's GADT solution, but doesn't impose the choice of data structure on you - you can use a Map instead of a list, for example:

import qualified Data.Map as M

mFoo :: M.Map String AnyFoo
mFoo = M.fromList [("a", AnyFoo SomeFoo), ("b", AnyFoo SomeBar)]

The data AnyFoo = forall a. Foo a => AnyFoo a bit can also be written in GADT notation as:

data AnyFoo where
  AnyFoo :: Foo a => a -> AnyFoo
like image 24
Mikhail Glushenkov Avatar answered Oct 19 '22 07:10

Mikhail Glushenkov