Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating different types from an unknown sequence, in Haskell?

Tags:

haskell

Assuming a function that "gets" a sequence of information (e.g. a list of characters), and shall create different types from it, where its type depends on the input sequence, which represents the content - and assuming the types are already given.

numFromString :: [Char] -> ???

I suppose there is several possibilities.

My first idea is to use a type parameter.

main :: IO ()
main =
    do
        sLine <- getLine
        print $ numFromString sLine

numFromString :: (Show a, Read a) => String -> (Maybe a)
numFromString ('I':'n':'t':'e':'g':'e':'r':rs) = Just ((read rs) :: Integer)
--                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this does not work
numFromString ('I':'n':'t':rs) = Just ((read rs) :: Int)
numFromString _ = Nothing

...but we cannot just provide an Integer where a type variable is expected or can we?.

My second idea is to use type class

main :: IO ()
main = 
    do
        sLine <- getLine
        print $ ((numFromString sLine) :: (Maybe Integer))
        --                                ^^^^^^^^^^^^^^^ I have to decide in advance which type I want to get

class (Show a, Read a) => XClass a where
    numFromString :: String -> (Maybe a)

instance XClass Int where
    numFromString ('I':'n':'t':rs) = Just ((read rs) :: Int)
    numFromString _ = Nothing

instance XClass Integer where
    numFromString ('I':'n':'t':'e':'g':'e':'r':rs) = Just ((read rs) :: Integer)
    numFromString _ = Nothing

...but this doesnt work as well, when we use numFromString, do we?.

My third idea is to use a sum kind of data type.

main :: IO ()
main =
    do
        sLine <- getLine
        print $ numFromString sLine

data X = XInt Int | XInteger Integer | XNone
    deriving Show

numFromString :: String -> X
numFromString ('I':'n':'t':'e':'g':'e':'r':rs) = XInteger (read rs)
numFromString ('I':'n':'t':rs) = XInt (read rs)
numFromString _ = XNone

Is there a more elegant way?

Would generic programming help?

How would it look like?

like image 285
Jörg Brüggmann Avatar asked May 28 '21 18:05

Jörg Brüggmann


People also ask

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.

What is nil Haskell?

The Nil constructor is an empty list. It contains no objects. So any time you're using the [] expression, you're actually using Nil . Then the second constructor concatenates a single element with another list.

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.

What is a point in Haskell?

The fields within a Haskell data type can be accessed either positionally or by name using field labels. Consider a data type for a two-dimensional point: data Point = Pt Float Float. The two components of a Point are the first and second arguments to the constructor Pt. A function such as.


1 Answers

Your sum type approach looks like the right way to me.

For examples of this in the wild:

  • The first character of a JSON document determines a type -- { for objects, [ for lists, " for strings, etc. aeson, a popular Haskell JSON parser, uses a sum type that can represent each of these.
  • An almost identical situation is involved in parsing CBOR. cborg uses a sum type to capture all the possibilities.
  • The Smart Games Format can represent the record of moves from a variety of games. The kind of information needed to store a move varies from game to game; the sgf library uses a sum type to capture the possibilities.

...and so on.

like image 94
Daniel Wagner Avatar answered Oct 21 '22 23:10

Daniel Wagner