Haskell unwrap data - haskell

If you have a data type
data Something = foo Integer
| bar Bool
Is there anyway I define "getters" that unwrap the Something type to get just the Integer or Bool? Right now it would be like (foo Integer) and (bar Bool). I just want the Integer or Boolean values.

Well, firstly you have a typo: data constructors must be uppercase:
data Something = Foo Integer
| Bar Bool
What you are asking for is exactly what pattern matching is for. If you have a Something value called s:
case s of
Foo f -> ... -- f is of type Integer in this "block"
Bar b -> ... -- b is of type Bool in this "block"
This is how you generally approach this problem, because any kind of getter on this sort of data type will throw an error if it is constructed with the "wrong" constructor, and this allows you to handle that case. You can make a safe getter with something like Maybe, but a lot of times this will end up involving more boilerplate anyway.

Related

How fromIntegral or read works

The fromIntegral returns a Num data type. But it seems that Num is able to coerce to Double or Integer with no issue. Similarly, the read function is able to return whatever that is required to fit its type signature. How does this works? And if I do need to make a similar function, how do I do it?
The type checker is able to infer not only the types of function arguments but also the return type. Actually there is no special case there. If you store the result of fromIntegral or read in Integer, the version for this type will get called. You can create your own function in the same way.
For example:
class Foo a where
foo :: a
instance Foo Integer where
foo = 7
instance Foo String where
foo = "Hello"
x :: Integer
x = 3
main = do
putStrLn foo
print (foo + x)
Because putStrLn has type String -> IO () the type checker finds that the type of foo in putStrLn foo must be String for the program to compile. The type of foo is Foo a => a. So it deduces that a == String and searches for Foo String instance. Such instance exists and it causes thefoo :: Foo String => String value to be selected there.
Similar reasoning happens in print (foo + x). x is known to be Integer, and because the type of (+) is Num a => a -> a -> a the type checker deduces that the left argument of the addition operator must also be Integer so it searches for Foo Integer instance and substitutes the Integer variant.
There is no direction from function arguments to (possible) return type like in C++. The type checker may even deduce function arguments based on knowledge of what the function is expected to return. Another example:
twice :: a -> [a]
twice a = [a,a]
y :: [Integer]
y = twice foo
The function argument here is of type Foo a => a which is not enough to decide which foo to use. But because the result is already known to be [Integer] the type checker finds that it has to provide value of type Integer to twice and does so by using the appropriate instance of foo.
read is a member of a typeclass which means that its implementation can depend on a type parameter.
Also, numeric literals like 1, 42, etc. are syntatic sugar for function calls fromInteger 1, fromInteger 42, etc., and fromInteger itself is a member of the Num typeclass.
Thus, the literal 42 (or fromInteger 42) can return an Int or Double or any other Num instance depending on the context in which it is called.
I'm being a little particular about terminology here, because I think the words you're using betray some misunderstandings about how Haskell works.
The fromIntegral returns a Num data type.
More precisely, fromIntegral takes as input any type that has an instance of class Integral, and can return any type that is an instance of class Num. The prelude defines it like this:
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInteger . toInteger
Types with an Integral instance implement thetoInteger function, and all types with a Num instance implement fromInteger. fromIntegral uses the toInteger associated with the Integral a instance to turn a value of type a into an Integer. Then it uses the fromInteger from the Num b instance to convert that Integer into a value of type b.
But it seems that Num is able to coerce to Double or Integer with no issue.
Every time a haskell function is used, it is "expanded". Its definition is substituted for the function call, and the parameters used are substituted into the definition. Each time it is expanded in a different context, it can have different types in its type variables. So each time a function is expanded, it takes certain concrete types and returns a certain concrete type. It doesn't return a typeless thing that gets coerced at some later time.
Similarly, the read function is able to return whatever that is required to fit its type signature.
read :: Read a => String -> a
read takes a String as input, and can be used in any context that returns values of a type for which an instance of class Read exists. When it is expanded during execution of a program, this type is known. It uses the particular definitions in the Read a instance to parse the string into the correct type.

Haskell type with derived value

Is it possible to have a type preform a function one of its value to generate another one of it's values? For instance:
data Foo=Foo {valueOne::Int, valueTwo=valueOne*2} deriving (Bar)
Or am I thinking about this in the wrong way? Any help is appreciated!
If you always want the second field to depend on the first, just write a plain function:
data Foo = Foo { valueOne :: Int } deriving (Bar)
valueTwo :: Foo -> Int
valueTwo x = valueOne x * 2
The only difference is that the Bar instance, which is automatically generated, won't notice the second field.
If, instead, you want to generate values with such constraint, but still be able to sometimes disregard that, use a smart constructor:
data Foo = Foo { valueOne :: Int, valueTwo :: Int } deriving (Bar)
foo :: Int -> Foo
foo x = Foo x (2 * x)
If you use foo instead of Foo to construct new values, you will not need to pass the second argument, which will be derived from the first one.
Usually this is used in a module which does not export the constructor Foo, but exports the smart constructor foo. In this way the users of the module are constrained to build values satisfying the invariant, while the functions in the module can ignore it, when needed.

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

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.

Is it possible to define a function in Haskell that has an input argument of two possible types?

For my own understanding, I want to define a function in Haskell that takes two arguments- either both Integers, or both Chars. It does some trivial examination of the arguments, like so:
foo 1 2 = 1
foo 2 1 = 0
foo 'a' 'b' = -1
foo _ _ = -10
This I know won't compile, because it doesn't know whether its args are of type Num or Char. But I can't make its arguments polymorphic, like:
foo :: a -> a -> Int
Because then we are saying it must be a Char (or Int) in the body.
Is it possible to do this in Haskell? I thought of maybe creating a custom type? Something like:
data Bar = Int | Char
foo :: Bar -> Bar -> Int
But I don't think this is valid either. In general, I'm confused about if there's a middle ground between a function in Haskell being either explicitly of ONE type, or polymorphic to a typeclass, prohibiting any usage of a specific type in the function body.
You can use the Either data type to store two different types. Something like this should work:
foo :: Either (Int, Int) (Char, Char) -> Int
foo (Right x) = 3
foo (Left y) = fst y
So, for it's Left data constructor you pass two Int to it and for it's Right constructor you pass two Char to it. Another way would be to define your own algebric data type like this:
data MyIntChar = MyInt (Int, Int) | MyChar (Char, Char) deriving (Show)
If you observe, then you can see that the above type is isomorphic to Either data type.
I'm not sure I would necessarily recommend using typeclasses for this, but they do make something like this possible at least.
class Foo a where
foo :: a -> a -> Int
instance Foo Int where
foo 1 2 = 1
foo 2 1 = 0
foo _ _ = -10
instance Foo Char where
foo 'a' 'b' = -1
foo _ _ = -10
You can do
type Bar = Either Int Char
foo :: Bar -> Bar -> Int
foo (Left 1) (Left 2) = 1
foo (Right 'a') (Right 'b') = -1
foo (Left 3) (Right 'q') = 42
foo _ _ = 10
and things like that - the Either data type is precisely for mixing two types together. You can roll your own similar type like
data Quux = AnInt Int | AChar Char | ThreeBools Bool Bool Bool
It's called an Algebraic Data Type.
(I struggle to think of circumstances when it's useful to mix specifically characters and integers together - mainly it's very helpful to know where your data is and what type it is.)
That said, I write algebraic data types a lot, but I give them meaningful names that represent actual things rather than just putting random stuff together because I don't like to be specific. Being very specific or completely general is useful. In between there are typeclasses like Eq. You can have a function with type Eq a => a -> [a] -> Bool which means it has type a -> [a] -> Bool for any type that has == defined, and I leave it open for people to use it for data types I never thought of as long as they define an equality function.

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.

Resources