How to get a value in a tagged union data type in Haskell? - haskell

In Haskell, if I create a dataype like this:
data MyT = MyT Int deriving (Show)
myValue = MyT 42
I can get the Int value passing 'myValue' to a function and doing pattern matching:
getInt :: MyT -> Int
getInt (MyT n) = n
It seems to me that something simpler should be possible. Is there another way?
Also, I tried a lambda function:
(\(MyT n) -> n) myValue
It doesn't work and I don't understand why not.
I get the error:
The function `\ (MyT n) -> n' is applied to two arguments,
but its type `MyT -> Int' has only one
EDIT:
Of course, sepp2k below, is right about my lambda function working OK. I was doing:
(\(MyT n) -> n) myT 42
instead of
(\(MyT n) -> n) (myT 42)

If you want to get at the value of MyT inside a larger function without defining a helper function, you could either use case of or pattern matching in local variable definitions. Here are examples of that (assuming that g produces a MyT and f takes an Int):
Using case:
myLargerFunction x = f (case g x of MyT n => n)
Or with local variables:
myLargerFunction x = f myInt
where MyT myInt = g x
Or using let instead of where:
myLargerFunction x =
let MyT myInt = g x in
f myInt
Your lambda function should (and in fact does) also work fine. Your error message suggests that in your real code you're really doing something like (\(MyT n) -> n) myValue somethingElse (presumably by accident).

You can use the record syntax
data MyT = MyT {unMyT :: Int} deriving (Show)
which gives you the projection for free
unMyT :: MyT -> Int
This is nice if your data type has only one constructor (including newtypes). For data types involving more than one constrctor, projection functions tend to be unsafe (e.g., head,tail), and pattern matching is usually preferred instead. GHC checks for non-exhaustive patterns if you enable warnings, and can help to spot errors.

NewTypes create a distinct type and do not have an extra level of indirection like algebraic datatypes. See the Haskell report for more information:
http://www.haskell.org/onlinereport/decls.html#sect4.2.3
Prelude> newtype Age = Age { unAge :: Int } deriving (Show)
Prelude> let personAge = Age 42
Prelude> personAge
Age {unAge = 42}
Prelude> (unAge personAge) + 1
43
Using a lambda function:
Prelude> (\(Age age) -> age * 2) personAge
84

Related

How might I be able to write multiple function definitions for multiple types in a polymorphic manner in Haskell?

Given my type definitions:
data Tile = Revealed | Covered deriving (Eq, Show)
data MinePit = Clean | Unsafe deriving (Eq, Show)
data Flag = Flagged | Unflagged deriving (Eq, Show)
type Square = (Tile, MinePit, Flag)
type Board = [[Square]]
I created two functions:
createBoard generates a 2D list of tuples of values -- or a 'Board'. It initialises a list of dimension n*m all of the same value.
createBoard :: Int -> Int -> Board
createBoard 0 _ = [[]]
createBoard _ 0 = [[]]
createBoard 1 1 = [[(Covered, Clean, Unflagged)]]
createBoard n m = take n (repeat (take m (repeat (Covered, Clean, Unflagged))))
An example:
λ> createBoard 2 3
[[(Covered,Clean,Unflagged),(Covered,Clean,Unflagged),(Covered,Clean,Unflagged)],[(Covered,Clean,Unflagged),(Covered,Clean,Unflagged),(Covered,Clean,Unflagged)]]
A function defineIndices was defined for the purpose of an in order list of indices for Board(s) produced by createBoard.
defineIndices :: Int -> Int -> [[(Int,Int)]]
defineIndices n m = [[(i,j) | j <- [1..m]] | i <- [1..n]]
It behaves like:
λ> defineIndices 2 3
[[(1,1),(1,2),(1,3)],[(2,1),(2,2),(2,3)]]
From here, I have created a function to create a MapBoard, where the values of a particular Square could be looked up given its indicies.
type MapBoard = Map (Int, Int) Square
createMapBoard :: [[(Int,Int)]] -> [[Square]] -> MapBoard
createMapBoard indices squares = M.fromList $ zip (concat indices) (concat squares)
However, it seemed reasonable to me that I should also write a method in which I can create a MapBoard directly from a pair of Int(s), implementing my prior functions. This might look like:
createMapBoard2 :: Int -> Int -> MapBoard
createMapBoard2 n m = createMapBoard indices squares where
indices = defineIndices n m
squares = createBoard n m
However, I looked up as to whether it is possible achieve polymorphism in this situataion with createMapBoard, and have createMapBoard2 be instead createMapBoard. I discovered online that this is called Ad-Hoc Polymorphism, and one can do e.g.
class Square a where
square :: a -> a
instance Square Int where
square x = x * x
instance Square Float where
square x = x * x
Attempting to write something similar myself, the best I could come up with is the following:
class MyClass a b MapBoard where
createMapBoard :: a -> b -> MapBoard
instance createMapBoard [[(Int,Int)]] -> [[Square]] -> MapBoard where
createMapBoard indices squares = M.fromList $ zip (concat indices) (concat squares)
instance createMapBoard Int -> Int -> MapBoard where
createMapBoard n m = createMapBoard indices squares where
indices = defineIndices n m
squares = createBoard n m
Attempting to compile this results in a Compilation error:
src/minesweeper.hs:35:19-26: error: …
Unexpected type ‘MapBoard’
In the class declaration for ‘MyClass’
A class declaration should have form
class MyClass a b c where ...
|
Compilation failed.
λ>
I am confused as to why I am not allowed to use a non-algebraic type such as MapBoard in the class definition.
class MyClass a b MapBoard where
Replacing MapBoard with another algebraic type c brings about another compilation error, which is lost on me.
src/minesweeper.hs:37:10-63: error: …
Illegal class instance: ‘createMapBoard [[(Int, Int)]]
-> [[Square]] -> MapBoard’
Class instances must be of the form
context => C ty_1 ... ty_n
where ‘C’ is a class
|
src/minesweeper.hs:39:10-46: error: …
Illegal class instance: ‘createMapBoard Int -> Int -> MapBoard’
Class instances must be of the form
context => C ty_1 ... ty_n
where ‘C’ is a class
|
Compilation failed.
Is it possible for me to achieve the ad-hoc polymorphism of createMapBoard? Am I able to create a class definition which has a strict constraint that the return type must be MapBoard for all instances?
Edit:
Having corrected the syntactic errors, my code is now:
class MyClass a b where
createMapBoard :: a -> b
instance createMapBoard [[(Int,Int)]] [[Square]] where
createMapBoard indices squares = M.fromList $ zip (concat indices) (concat squares)
instance createMapBoard Int Int where
createMapBoard n m = createMapBoard indices squares where
indices = defineIndices n m
squares = createBoard n m
This leads to yet another compilation error:
src/minesweeper.hs:37:10-23: error: …
Not in scope: type variable ‘createMapBoard’
|
src/minesweeper.hs:39:10-23: error: …
Not in scope: type variable ‘createMapBoard’
|
Compilation failed.
I am inclined to believe that an error in my understanding of classes is still present.
You want to write it this way:
class MyClass a b where createMapBoard :: a -> b -> MapBoard
instance MyClass [[(Int,Int)]] [[Square]] where
createMapBoard indices squares = M.fromList $ zip ...
instance MyClass Int Int where
createMapBoard n m = createMapBoard indices squares where
...
The ... -> ... -> MapBoard is already in the createMapBoard method's signature, this doesn't belong in the class / instance heads.
Incidentally, I'm not convinced that it really makes sense to have a class here at all. There's nothing wrong with having two separately named createMapBoard functions. A class only is the way to go if you can actually write polymorphic functions over it, but in this case I doubt it – you'd rather have either the concrete situation where you need the one version, or the other. There's no need for a class then, just hard-write which version it is you want.
One reason for rather going with separate functions than a class method is that it makes the type checker's work easier. As soon as the arguments of createMapBoard are polymorphic, they could potentially have any type (at least as far as the type checker is concerned). So you can only call it with arguments whose type is fully determined elsewhere. Now, in other programming languages the type of values you might want to pass is generally fixed anyway, but in Haskell it's actually extremely common to have also polymorphic values. The simplest example is number literals – they don't have type Int or so, but Num a => a.
I personally find “reverse polymorphism” normally nicer to work with than “forward polymorphism”: don't make the arguments to functions polymorphic, but rather the results. This way, it's enough to have the outermost type of an expression fixed by the environment, and automatically all the subexpressions are inferred by the type checker. The other way around, you have to have all the individual expressions' types fixed, and the compiler can infer the final result type... which is hardly useful because you probably want to fix that by a signature anyway.

Check if it is a specific type - haskell

I thought it would be really easy to find the answer online but I had no luck with that. Which means that my question should't be a question but I am sure more people new to Haskell might come up with the same question.
So how do I check if a value is of a certain type?
I have the following data type defined and I wanna check whether the input on a function is of a specific type.
data MyType a = MyInt Int | MyOther a (MyType a)
First, your data declaration will not work. Let's assume you're using this type:
data MyType a = MyInt Int | MyOther a (MyType a)
then you can have functions that take a MyType a, some specific MyType (e.g. MyType Int) or a constrained MyType (e.g. Num a => MyType a).
If you want to know whether you have a MyInt or a MyOther, you can simply use pattern matching:
whichAmI :: MyType a -> String
whichAmI (MyInt i) = "I'm an Int with value " ++ show i
whichAmI (MyOther _ _) = "I'm something else"
When you want to know if the type in the parameter a is a Num, or what type it is, you will run into a fundamental Haskell limitation. Haskell is statically typed so there is no such dynamic checking of what the a in MyType a is.
The solution is to limit your function if you need a certain type of a. For example we can have:
mySum :: Num a => MyType a -> a
mySum (MyInt i) = fromIntegral i
mySum (MyOther n m) = n + mySum m
or we can have a function that only works if a is a Bool:
trueOrGE10 :: MyType Bool -> Bool
trueOrGE10 (MyInt i) = i >= 10
trueOrGE10 (MyOther b _) = b
As with all Haskell code, it will need to be possible to determine at compile-time whether a particular expression you put into one of these functions has the right type.

Is there a compiler-extension for untagged union types in Haskell?

In some languages (#racket/typed, for example), the programmer can specify a union type without discriminating against it, for instance, the type (U Integer String) captures integers and strings, without tagging them (I Integer) (S String) in a data IntOrStringUnion = ... form or anything like that.
Is there a way to do the same in Haskell?
Either is what you're looking for... ish.
In Haskell terms, I'd describe what you're looking for as an anonymous sum type. By anonymous, I mean that it doesn't have a defined name (like something with a data declaration). By sum type, I mean a data type that can have one of several (distinguishable) types; a tagged union or such. (If you're not familiar with this terminology, try Wikipedia for starters.)
We have a well-known idiomatic anonymous product type, which is just a tuple. If you want to have both an Int and a String, you just smush them together with a comma: (Int, String). And tuples (seemingly) can go on forever--(Int, String, Double, Word), and you can pattern-match the same way. (There's a limit, but never mind.)
The well-known idiomatic anonymous sum type is Either, from Data.Either (and the Prelude):
data Either a b = Left a | Right b
deriving (Eq, Ord, Read, Show, Typeable)
It has some shortcomings, most prominently a Functor instance that favors Right in a way that's odd in this context. The problem is that chaining it introduces a lot of awkwardness: the type ends up like Either (Int (Either String (Either Double Word))). Pattern matching is even more awkward, as others have noted.
I just want to note that we can get closer to (what I understand to be) the Racket use case. From my extremely brief Googling, it looks like in Racket you can use functions like isNumber? to determine what type is actually in a given value of a union type. In Haskell, we usually do that with case analysis (pattern matching), but that's awkward with Either, and function using simple pattern-matching will likely end up hard-wired to a particular union type. We can do better.
IsNumber?
I'm going to write a function I think is an idiomatic Haskell stand-in for isNumber?. First, we don't like doing Boolean tests and then running functions that assume their result; instead, we tend to just convert to Maybe and go from there. So the function's type will end with -> Maybe Int. (Using Int as a stand-in for now.)
But what's on the left hand of the arrow? "Something that might be an Int -- or a String, or whatever other types we put in the union." Uh, okay. So it's going to be one of a number of types. That sounds like typeclass, so we'll put a constraint and a type variable on the left hand of the arrow: MightBeInt a => a -> Maybe Int. Okay, let's write out the class:
class MightBeInt a where
isInt :: a -> Maybe Int
fromInt :: Int -> a
Okay, now how do we write the instances? Well, we know if the first parameter to Either is Int, we're golden, so let's write that out. (Incidentally, if you want a nice exercise, only look at the instance ... where parts of these next three code blocks, and try to implement that class members yourself.)
instance MightBeInt (Either Int b) where
isInt (Left i) = Just i
isInt _ = Nothing
fromInt = Left
Fine. And ditto if Int is the second parameter:
instance MightBeInt (Either a Int) where
isInt (Right i) = Just i
isInt _ = Nothing
fromInt = Right
But what about Either String (Either Bool Int)? The trick is to recurse on the right hand type: if it's not Int, is it an instance of MightBeInt itself?
instance MightBeInt b => MightBeInt (Either a b) where
isInt (Right xs) = isInt xs
isInt _ = Nothing
fromInt = Right . fromInt
(Note that these all require FlexibleInstances and OverlappingInstances.) It took me a long time to get a feel for writing and reading these class instances; don't worry if this instance is surprising. The punch line is that we can now do this:
anInt1 :: Either Int String
anInt1 = fromInt 1
anInt2 :: Either String (Either Int Double)
anInt2 = fromInt 2
anInt3 :: Either String Int
anInt3 = fromInt 3
notAnInt :: Either String Int
notAnInt = Left "notint"
ghci> isInt anInt3
Just 3
ghci> isInt notAnInt
Nothing
Great!
Generalizing
Okay, but now do we need to write another type class for each type we want to look up? Nope! We can parameterize the class by the type we want to look up! It's a pretty mechanical translation; the only question is how to tell the compiler what type we're looking for, and that's where Proxy comes to the rescue. (If you don't want to install tagged or run base 4.7, just define data Proxy a = Proxy. It's nothing special, but you'll need PolyKinds.)
class MightBeA t a where
isA :: proxy t -> a -> Maybe t
fromA :: t -> a
instance MightBeA t t where
isA _ = Just
fromA = id
instance MightBeA t (Either t b) where
isA _ (Left i) = Just i
isA _ _ = Nothing
fromA = Left
instance MightBeA t b => MightBeA t (Either a b) where
isA p (Right xs) = isA p xs
isA _ _ = Nothing
fromA = Right . fromA
ghci> isA (Proxy :: Proxy Int) anInt3
Just 3
ghci> isA (Proxy :: Proxy String) notAnInt
Just "notint"
Now the usability situation is... better. The main thing we've lost, by the way, is the exhaustiveness checker.
Notational Parity With (U String Int Double)
For fun, in GHC 7.8 we can use DataKinds and TypeFamilies to eliminate the infix type constructors in favor of type-level lists. (In Haskell, you can't have one type constructor--like IO or Either--take a variable number of parameters, but a type-level list is just one parameter.) It's just a few lines, which I'm not really going to explain:
type family OneOf (as :: [*]) :: * where
OneOf '[] = Void
OneOf '[a] = a
OneOf (a ': as) = Either a (OneOf as)
Note that you'll need to import Data.Void. Now we can do this:
anInt4 :: OneOf '[Int, Double, Float, String]
anInt4 = fromInt 4
ghci> :kind! OneOf '[Int, Double, Float, String]
OneOf '[Int, Double, Float, String] :: *
= Either Int (Either Double (Either Float [Char]))
In other words, OneOf '[Int, Double, Float, String] is the same as Either Int (Either Double (Either Float [Char])).
You need some kind of tagging because you need to be able to check if a value is actually an Integer or a String to use it for anything. One way to alleviate having to create a custom ADT for every combination is to use a type such as
{-# LANGUAGE TypeOperators #-}
data a :+: b = L a | R b
infixr 6 :+:
returnsIntOrString :: Integer -> Integer :+: String
returnsIntOrString i
| i `rem` 2 == 0 = R "Even"
| otherwise = L (i * 2)
returnsOneOfThree :: Integer -> Integer :+: String :+: Bool
returnsOneOfThree i
| i `rem` 2 == 0 = (R . L) "Even"
| i `rem` 3 == 0 = (R . R) False
| otherwise = L (i * 2)

Lens package with algebraic types

I was coding with with the lens package. Everything was going fine until I tried to access a certain field on an algebraic type:
import Control.Lens
data Type = A { _a :: Char } | B
makeLenses ''Type
test1 = _a (A 'a')
test2 = (A 'a') ^. a
No instance for (Data.Monoid.Monoid Char)
arising from a use of `a'
Possible fix:
add an instance declaration for (Data.Monoid.Monoid Char)
In the second argument of `(^.)', namely `a'
In the expression: (A 'a') ^. a
In an equation for `test2': test2 = (A 'a') ^. a
I could just go with _a, but the datatype in my real program is much deeper and I kind of intended on using lens to lower the amount of work I have to do. I have been looking over the lens library but there's so much there, and I'm not sure if he's dealt with this scenario or it is just something the lens library doesn't support.
As a side note, if I actually use a monoid like String for the datatype instead of Char, it then compiles and gives the right answer, I have no idea why.
Edit: After reading hammar's comment, I tried this and this works:
test2 = (A 'a') ^? a
test3 = B ^? a
But it is kind of weird to get a maybe out of that for something that has to exist.
Just so that this is answered, my problem was that I had an algebraic type where some fields were in common between the different constructors but there was a couple fields that weren't shared would die in runtime if I tried to use them.
data Exercise =
BarbellExercise {
name :: String,
weight :: Int,
reps :: Int
} |
BodyWeightExercise {
name :: String,
reps :: Int
}
exer1 = BarbellExercise "Squats" 235 15
exer2 = BarbellExercise "Deadlifts" 265 15
exer3 = BodyWeightExercise "Pullups" 12
exer4 = BarbellExercise "Overhead Press" 85 15
workout = [exer1, exer2, exer3, exer4]
test = do
mapM_ displayExercise workout
where
displayExercise x = putStrLn $ "Exercise: " ++ (name x) ++ " You must perform " ++ (show $ reps x) ++ "#" ++ (show $ weight x)
This compiles but dies runtime if I make the mistake of using the weight function. Understandable mistake. When lenses uses template haskell to generate instances it notices this and changes its behavior to prevent a mistake. You could remove the field accessors but in my case most of the fields were the same between datatypes. Here's how I should have written the data type once I noticed the fields did not match up:
data Exercise =
BarbellExercise
String -- ^ name
Int -- ^ reps
Int -- ^ weight
|
BodyWeightExercise
String -- ^ name
Int -- reps
name :: Exercise -> String
name (BarbellExercise n _ _) = n
name (BodyWeightExercise n _) = n
reps :: Exercise -> Int
reps (BarbellExercise _ r _) = r
reps (BodyWeightExercise _ r) = r
By doing it this way, while it is a little less clean, the error are caught at compile time. By forcing me to write the functions myself I would notice any partial functions as I was writing them.
I do kind of wish ghc would have warned me. It seems like it would be really easy for it to detect such a thing.

How to declare function (type misunderstanding Maybe)

I need a function which works like:
some :: (Int, Maybe Int) -> Int
some a b
| b == Nothing = 0
| otherwise = a + b
Use cases:
some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]
But my code raise the error:
The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one
I don't understand it.
Thanks in advance.
When you write
foo x y = ...
That is notation for a curried function, with a type like:
foo :: a -> b -> c
You have declared your function to expect a tuple, so you must write it:
some :: (Int, Maybe Int) -> Int
some (x, y) = ...
But Haskell convention is usually to take arguments in the former curried form. Seeing funcitons take tuples as arguments is very rare.
For the other part of your question, you probably want to express it with pattern matching. You could say:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1
Generalizing that to the OP's question is left as an exercise for the reader.
Your error doesn't come from a misunderstanding of Maybe: The type signature of some indicates that it takes a pair (Int, Maybe Int), while in your definition you provide it two arguments. The definition should thus begin with some (a,b) to match the type signature.
One way to fix the problem (which is also a bit more idiomatic and uses pattern matching) is:
some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b
It's also worth noting that unless you have a really good reason for using a tuple as input, you should probably not do so. If your signature were instead some :: Int -> Maybe Int -> Int, you'd have a function of two arguments, which can be curried. Then you'd write something like
some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b
Also, you might want to add the following immediate generalization: All Num types are additive, so you might aswell do
some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b
(I've violated the common practice of using a, b, c... for type variables so as not to confuse the OP since he binds a and b to the arguments of some).

Resources