Lens package with algebraic types - haskell

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.

Related

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)

haskell writing constructors that do work in them

i have a few questions
Im writing this constructor called rope which i have like this
data Rope = TextRope{ropeText :: String}
| ConcatRope{rope1 :: Rope, rope2 :: Rope}
| SubRope{subRopetext :: Rope, starting :: Integer, ending :: Integer}
deriving Show
First off when i make a TextRope like this
*Main> let s =TextRope "why"
*Main> s
TextRope {ropeText = "why"}
*Main>
when i do s i want to just get the string of the constructor which is why and im not really sure about that.
Also curious about concat and sub constructors. Specifically it seems like to me you are calling these two constructors there is things happening, you are returning the result of concatenating rope 1 and rope 2 together, im not sure how to describe that in this language, you are defining the data structure but somehow the return of that is a result that has to be calculated by the structure
Here are some examples of what how these functions work
> let tr = TextRope "Hello,"
> let sr = TextRope " world!"
> let hw = ConcatRope tr sr
> let ow = SubRope hw 4 4
> tr
Hello,
> sr
world!
> hw
Hello, world!
Sort of confused overall, new to haskell constructors and datatypes, so some pointers would be helpful (not c pointers though!)
Data constructors never do work. They only hold the data you pass into them. If you want work to be done, you should define what are called smart constructors, which are just functions that perform some operation before passing it to the actual constructor. An example might be
data Fraction = Fraction
{ numerator :: Int
, denominator :: Int
} deriving (Eq)
(%) :: Int -> Int -> Fraction
x % y =
let (a, b) = reduce x y
in Fraction a b
-- Reduces a fraction to it's simplest terms
reduce :: Int -> Int -> (Int, Int)
reduce num den = undefined
Here you wouldn't export the Fraction constructor from your module, just the % function that constructs one in the most reduced form.
The other problem you have is that you want your constructors to print out differently. You can achieve this by not deriving Show. However, I will warn that the Haskell convention is that show . read = read . show = id, which wouldn't hold for what you want to do. This isn't a strict convention, though, and there's nothing stopping you from doing something like:
data Rope = <your implementation minus the deriving Show bit>
instance Show Rope where
show (TextRope t) = t
show (ConcatRope r1 r2) = show r1 ++ show r2
show (SubRope r starting ending) = <exercise left to reader>
As an aside, I would recommend against having a sum type of records with different field names, this can lead to problems where your program type-checks but contains errors that can be caught at compile time if written differently. For example, what would happen if you had the code
> ropeText (ConcatRope (TextRope "Hello, ") (TextRope "world!"))
This would cause an error and crash your program! Instead, it looks like you just want a Rope type with concat and subRope functions, so you could implement it very simply as
data Rope = Rope String deriving (Eq)
concatRope :: Rope -> Rope -> Rope
concatRope (Rope r1) (Rope r2) = Rope (r1 ++ r2)
-- Why use Integer instead of Int? You might find it's easier to implement this function
subRope :: Rope -> Integer -> Integer -> Rope
subRope (Rope r) start end = Rope $ substr start end r
where substr s e text = <exercise left to reader>
Now there's absolutely no way to have an illegal rope operation, the only difference is now you have to use concatRope in place of ConcatRope and subRope in place of SubRope. You're guaranteed that these functions will do what you want, you don't have some complicated type that doesn't help you anyway.
if you don't implement your own show (not with auto-deriving) you will have a harder time getting what you want.
But if you do it's kindof easy:
data Rope = TextRope{ropeText :: String}
| ConcatRope{rope1 :: Rope, rope2 :: Rope}
| SubRope{subRopetext :: Rope, starting :: Integer, ending :: Integer}
instance Show Rope where
show (TextRope s) = s
show (ConcatRope a b) = show a ++ show b
I'm sure you'll find the implementation for the SubRope case youself ;)
Your example code and your example interactive results don't match. This is how you've defined Rope:
data Rope = TextRope{ropeText :: String}
| ConcatRope{rope1 :: Rope, rope2 :: Rope}
| SubRope{subRopetext :: Rope, starting :: Integer, ending :: Integer}
deriving Show
The deriving Show part is key there; we'll see how.
Later you show this example output:
> let tr = TextRope "Hello,"
> let sr = TextRope " world!"
> let hw = ConcatRope tr sr
> hw
Hello, world!
With the code that I just showed, actually, what you'll see is the following:
> hw
ConcatRope { rope1 = TextRope "Hello,", rope2 = TextRope " world!" }
The only way we could get the output that you describe is if we got rid of the deriving Show clause in your definition of Rope, and wrote this:
instance Show Rope where
show (TextRope text) = text
show (ConcatRope r1 r2) = show r1 ++ show r2
show (SubRope rope start end) = ...

How to get a value in a tagged union data type in 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

Create a type that can contain an int and a string in either order

I'm following this introduction to Haskell, and this particular place (user defined types 2.2) I'm finding particularly obscure. To the point, I don't even understand what part of it is code, and what part is the thoughts of the author. (What is Pt - it is never defined anywhere?). Needless to say, I can't execute / compile it.
As an example that would make it easier for me to understand, I wanted to define a type, which is a pair of an Integer and a String, or a String and an Integer, but nothing else.
The theoretical function that would use it would look like so:
combine :: StringIntPair -> String
combine a b = (show a) ++ b
combine a b = a ++ (show b)
If you need a working code, that does the same, here's CL code for doing it:
(defgeneric combine (a b)
(:documentation "Combines strings and integers"))
(defmethod combine ((a string) (b integer))
(concatenate 'string a (write-to-string b)))
(defmethod combine ((a integer) (b string))
(concatenate 'string (write-to-string a) b))
(combine 100 "500")
Here's one way to define the datatype:
data StringIntPair = StringInt String Int |
IntString Int String
deriving (Show, Eq, Ord)
Note that I've defined two constructors for type StringIntPair, and they are StringInt and IntString.
Now in the definition of combine:
combine :: StringIntPair -> String
combine (StringInt s i) = s ++ (show i)
combine (IntString i s) = (show i) ++ s
I'm using pattern matching to match the constructors and select the correct behavior.
Here are some examples of usage:
*Main> let y = StringInt "abc" 123
*Main> let z = IntString 789 "a string"
*Main> combine y
"abc123"
*Main> combine z
"789a string"
*Main> :t y
y :: StringIntPair
*Main> :t z
z :: StringIntPair
A few things to note about the examples:
StringIntPair is a type; doing :t <expression> in the interpreter shows the type of an expression
StringInt and IntString are constructors of the same type
the vertical bar (|) separates constructors
a well-written function should match each constructor of its argument's types; that's why I've written combine with two patterns, one for each constructor
data StringIntPair = StringInt String Int
| IntString Int String
combine :: StringIntPair -> String
combine (StringInt s i) = s ++ (show i)
combine (IntString i s) = (show i) ++ s
So it can be used like that:
> combine $ StringInt "asdf" 3
"asdf3"
> combine $ IntString 4 "fasdf"
"4fasdf"
Since Haskell is strongly typed, you always know what type a variable has. Additionally, you will never know more. For instance, consider the function length that calculates the length of a list. It has the type:
length :: [a] -> Int
That is, it takes a list of arbitrary a (although all elements have the same type) and returns and Int. The function may never look inside one of the lists node and inspect what is stored in there, since it hasn't and can't get any informations about what type that stuff stored has. This makes Haskell pretty efficient, since, as opposed to typical OOP languages such as Java, no type information has to be stored at runtime.
To make it possible to have different types of variables in one parameter, one can use an Algebraic Data Type (ADT). One, that stores either a String and an Int or an Int and a String can be defined as:
data StringIntPair = StringInt String Int
| IntString Int String
You can find out about which of the two is taken by pattern matching on the parameter. (Notice that you have only one, since both the string and the in are encapsulated in an ADT):
combine :: StringIntPair -> String
combine (StringInt str int) = str ++ show int
combine (IntString int str) = show int ++ str

Sort by constructor ignoring (part of) value

Suppose I have
data Foo = A String Int | B Int
I want to take an xs :: [Foo] and sort it such that all the As are at the beginning, sorted by their strings, but with the ints in the order they appeared in the list, and then have all the Bs at the end, in the same order they appeared.
In particular, I want to create a new list containg the first A of each string and the first B.
I did this by defining a function taking Foos to (Int, String)s and using sortBy and groupBy.
Is there a cleaner way to do this? Preferably one that generalizes to at least 10 constructors.
Typeable, maybe? Something else that's nicer?
EDIT: This is used for processing a list of Foos that is used elsewhere. There is already an Ord instance which is the normal ordering.
You can use
sortBy (comparing foo)
where foo is a function that extracts the interesting parts into something comparable (e.g. Ints).
In the example, since you want the As sorted by their Strings, a mapping to Int with the desired properties would be too complicated, so we use a compound target type.
foo (A s _) = (0,s)
foo (B _) = (1,"")
would be a possible helper. This is more or less equivalent to Tikhon Jelvis' suggestion, but it leaves space for the natural Ord instance.
To make it easier to build comparison function for ADTs with large number of constructors, you can map values to their constructor index with SYB:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Generics
data Foo = A String Int | B Int deriving (Show, Eq, Typeable, Data)
cIndex :: Data a => a -> Int
cIndex = constrIndex . toConstr
Example:
*Main Data.Generics> cIndex $ A "foo" 42
1
*Main Data.Generics> cIndex $ B 0
2
Edit:After re-reading your question, I think the best option is to make Foo an instance of Ord. I do not think there is any way to do this automatically that will act the way you want (just using deriving will create different behavior).
Once Foo is an instance of Ord, you can just use sort from Data.List.
In your exact example, you can do something like this:
data Foo = A String Int | B Int deriving (Eq)
instance Ord Foo where
(A _ _) <= (B _) = True
(A s _) <= (A s' _) = s <= s'
(B _) <= (B _) = True
When something is an instance of Ord, it means the data type has some ordering. Once we know how to order something, we can use a bunch of existing functions (like sort) on it and it will behave how you want. Anything in Ord has to be part of Eq, which is what the deriving (Eq) bit does automatically.
You can also derive Ord. However, the behavior will not be exactly what you want--it will order by all of the fields if it has to (e.g. it will put As with the same string in order by their integers).
Further edit: I was thinking about it some more and realized my solution is probably semantically wrong.
An Ord instance is a statement about your whole data type. For example, I'm saying that Bs are always equal with each other when the derived Eq instance says otherwise.
If the data your representing always behaves like this (that is, Bs are all equal and As with the same string are all equal) then an Ord instance makes sense. Otherwise, you should not actually do this.
However, you can do something almost exactly like this: write your own special compare function (Foo -> Foo -> Ordering) that encapsulates exactly what you want to do then use sortBy. This properly codifies that your particular sorting is special rather than the natural ordering of the data type.
You could use some template haskell to fill in the missing transitive cases. The mkTransitiveLt creates the transitive closure of the given cases (if you order them least to greatest). This gives you a working less-than, which can be turned into a function that returns an Ordering.
{-# LANGUAGE TemplateHaskell #-}
import MkTransitiveLt
import Data.List (sortBy)
data Foo = A String Int | B Int | C | D | E deriving(Show)
cmp a b = $(mkTransitiveLt [|
case (a, b) of
(A _ _, B _) -> True
(B _, C) -> True
(C, D) -> True
(D, E) -> True
(A s _, A s' _) -> s < s'
otherwise -> False|])
lt2Ord f a b =
case (f a b, f b a) of
(True, _) -> LT
(_, True) -> GT
otherwise -> EQ
main = print $ sortBy (lt2Ord cmp) [A "Z" 1, A "A" 1, B 1, A "A" 0, C]
Generates:
[A "A" 1,A "A" 0,A "Z" 1,B 1,C]
mkTransitiveLt must be defined in a separate module:
module MkTransitiveLt (mkTransitiveLt)
where
import Language.Haskell.TH
mkTransitiveLt :: ExpQ -> ExpQ
mkTransitiveLt eq = do
CaseE e ms <- eq
return . CaseE e . reverse . foldl go [] $ ms
where
go ms m#(Match (TupP [a, b]) body decls) = (m:ms) ++
[Match (TupP [x, b]) body decls | Match (TupP [x, y]) _ _ <- ms, y == a]
go ms m = m:ms

Resources