Let's say I have a list of twelve musical notes (which have their own data type), and I want a function that returns a list of notes starting with a given note and looping around.
data Note = C | CsDb | D | DsEb | E | F | FsGb | G | GsAb | A | AsBb | B deriving (Read, Eq, Ord, Enum, Bounded)
getNotes :: Note -> [Note]
getNotes root = take 12 $ doSomething root $ cycle noteList
where noteList :: [Note]
noteList = [minBound..maxBound]
such that
ghci> getNotes E
[E, F, FsGb, G, GsAb, A, AsBb, B, C, CsDb, D, DsEb]
I can think of a few sloppy ways to do this, but it feels like there should be an obvious, very Haskellian way. Any recommendations?
I'd just
getNotes root = [root .. maxBound] ++ init [minBound .. root]
but I can see how you prefer the cyclic approach. How about
getNotes root = map snd . take 12 $ [(0,root) .. ]
...sadly, that doesn't in fact work: it would need a (Enum a, Enum b, Bounded b) => Enum (a,b) instance, which for some reason isn't defined, at least not in the prelude.
Alternatively, you can use the index of root:
getNotes root = take 12 . drop (fromEnum root) $ cycle [minBound .. maxBound]
The smallest change you can make that works is to use dropWhile:
getNotes :: Note -> [Note]
getNotes root = take 12 . dropWhile (/= root) . cycle $ [minBound .. maxBound]
Based on the second idea of #leftaroundabout this is a working version - just in case you are curious and want to play with it:
{-# LANGUAGE ScopedTypeVariables #-}
module Stackoverflow where
data Note = C | CsDb | D | DsEb | E | F | FsGb | G | GsAb | A | AsBb | B
deriving (Show, Enum, Bounded)
instance (Enum a, Enum b, Bounded b) => Enum (a,b) where
toEnum i =
let (d,m) = i `divMod` (fromEnum (maxBound :: b) + 1)
in (toEnum d, toEnum m)
fromEnum (a, b) = fromEnum a * (fromEnum (maxBound :: b) + 1) + fromEnum b
getNotes :: Note -> [Note]
getNotes root = map snd . take 12 $ [(0,root) .. ]
example:
λ> getNotes E
[E,F,FsGb,G,GsAb,A,AsBb,B,C,CsDb,D,DsEb]
PS: the idea is extremely smart #leftaroundabout <- so guys make sure to give him lot's of upvotes ;)
How about
getNotes :: Note -> [Note]
getNotes root = ys ++ xs where (xs,ys) = break (==root) [minBound..maxBound]
? This is more-or-less the same as #leftaroundabout's first suggestion, avoids the init, but incurs a number of equality comparisons :-)
Related
When I want to read string to type A I write read str::A. Consider, I want to have generic function which can read string to different types, so I want to write something like read str::A|||B|||C or something similar. The only thing I could think of is:
{-# LANGUAGE TypeOperators #-}
infixr 9 |||
data a ||| b = A a|B b deriving Show
-- OR THIS:
-- data a ||| b = N | A a (a ||| b) | B b (a ||| b) deriving (Data, Show)
instance (Read a, Read b) => Read (a ||| b) where
readPrec = parens $ do
a <- (A <$> readPrec) <|> (B <$> readPrec)
-- OR:
-- a <- (flip A N <$> readPrec) <|> (flip B N <$> readPrec)
return a
And if I want to read something:
> read "'a'"::Int|||Char|||String
B (A 'a')
But what to do with such weird type? I want to fold it to Int or to Char or to String... Or to something another but "atomic" (scalar/simple). Final goal is to read strings like "1,'a'" to list-like [D 1, D 'a']. And main constraint here is that structure is flexible, so string can be "1, 'a'" or "'a', 1" or "\"xxx\", 1, 2, 'a'". I know how to read something separated with delimiter, but this something should be passed as type, not as sum of types like C Char|I Int|S String|etc. Is it possible? Or no way to accomplish it without sum of types?
There’s no way to do this in general using read, because the same input string might parse correctly to more than one of the valid types. You could, however, do this with a function like Text.Read.readMaybe, which returns Nothing on ambiguous input. You might also return a tuple or list of the valid interpretations, or have a rule for which order to attempt to parse the types in, such as: attempt to parse each type in the order they were declared.
Here’s some example code, as proof of concept:
import Data.Maybe (catMaybes, fromJust, isJust, isNothing)
import qualified Text.Read
data AnyOf3 a b c = FirstOf3 a | SecondOf3 b | ThirdOf3 c
instance (Show a, Show b, Show c) => Show (AnyOf3 a b c) where
show (FirstOf3 x) = show x -- Can infer the type from the pattern guard.
show (SecondOf3 x) = show x
show (ThirdOf3 x) = show x
main :: IO ()
main =
(putStrLn . unwords . map show . catMaybes . map readDBS)
["True", "2", "\"foo\"", "bar"] >>
(putStrLn . unwords . map show . readIID) "100"
readMaybe' :: (Read a, Read b, Read c) => String -> Maybe (AnyOf3 a b c)
-- Based on the function from Text.Read
readMaybe' x | isJust a && isNothing b && isNothing c =
(Just . FirstOf3 . fromJust) a -- Can infer the type of a from this.
| isNothing a && isJust b && isNothing c =
(Just . SecondOf3 . fromJust) b -- Can infer the type of b from this.
| isNothing a && isNothing b && isJust c =
(Just . ThirdOf3 . fromJust) c -- Can infer the type of c from this.
| otherwise = Nothing
where a = Text.Read.readMaybe x
b = Text.Read.readMaybe x
c = Text.Read.readMaybe x
readDBS :: String -> Maybe (AnyOf3 Double Bool String)
readDBS = readMaybe'
readToList :: (Read a, Read b, Read c) => String -> [AnyOf3 a b c]
readToList x = repack FirstOf3 x ++ repack SecondOf3 x ++ repack ThirdOf3 x
where repack constructor y | isJust z = [(constructor . fromJust) z]
| otherwise = []
where z = Text.Read.readMaybe y
readIID :: String -> [AnyOf3 Int Integer Double]
readIID = readToList
The first output line echoes every input that parsed successfully, that is, the Boolean constant, the number and the quoted string, but not bar. The second output line echoes every possible interpretation of the input, that is, 100 as an Int, an Integer and a Double.
For something more complicated, you want to write a parser. Haskell has some very good libraries to build them out of combinators. You might look at one such as Parsec. But it’s still helpful to understand what goes on under the hood.
The following program has as its purpose the transitive closure of relation (as a set of ordered pairs - a graph) and a test about membership of an ordered pair to that relation.
I tried to make the program efficient through the use of Data.Set instead of lists and eliminating redundancies in the generation of the missing pair.
I would like to know:
how to use QuickCheck to verify its correctness;
how calculate the efficiency of the program, if it is possible, or
how does it compare with similar solutions of the problem (ex.
Transitive closure from a list ).
Any criticism and suggestion will be appreciated.
import Data.Set as S
import Data.Foldable as F (foldMap)
data TruthValue = F | U | T deriving (Show,Eq)
isMemberOfTransitiveGraph :: Ord t => (t, t) -> Set (t, t) -> TruthValue
(x,y) `isMemberOfTransitiveGraph` gr
| S.member (x,y) closure = T -- as suggested by user5402
| S.member (y,x) closure = F -- as suggested by user5402
| otherwise = U
where
closure = transitiveClusureOfGraph gr -- as suggested by user5402
transitiveClusureOfGraph :: Ord a => Set (a, a) -> Set (a, a)
transitiveClusureOfGraph gr = F.foldMap (transitiveClosureOfArgument gr) domain
where
domain = S.map fst gr
transitiveClosureOfArgument :: Ord a => Set (a, a) -> a -> Set (a, a)
transitiveClosureOfArgument gr x = S.map ((,) x) $ recursiveImages gr (S.singleton x)
recursiveImages :: Ord a => Set (a, a) -> Set a -> Set a
recursiveImages gr imgs = f gr imgs S.empty
where
f :: Ord a => Set (a, a) -> Set a -> Set a -> Set a
f gr imgs acc
| S.null imgs = acc
| otherwise = f gr (newImgs S.\\ acc) (S.union newImgs acc)
where
newImgs = F.foldMap (imaginsOf gr) imgs
imaginsOf :: (Ord b, Eq a) => Set (a, b) -> a -> Set b
imaginsOf gr arg = S.foldr (\(a,b) acc -> if a == arg then S.insert b acc else acc) S.empty gr
**
EXAMPLE 1
**
someLessThan = S.fromList [("1","2"),("1","4"),("3","4"),("2","8"),("3","5"),("4","7"),("4","8"),("3","9")]
> transitiveClusureOfGraph someLessThan
> fromList [("1","2"),("1","4"),("1","7"),("1","8"),("2","8"),("3","4"),("3","5"),("3","7"),("3","8"),("3","9"),("4","7"),("4","8")]
a `isLessThan` b = (a,b) `isMemberOfTransitiveGraph` someLessThan
> "1" `isLessThan` "8"
> T
> "8" `isLessThan` "1"
> F
> "1" `isLessThan` "9"
> U
> "9" `isLessThan` "1"
> U
**
EXAMPLE 2
**
someTallerThan = S.fromList [("Alexandre","Andrea"),("Andrea","John"),("George","Frank"),("George","Lucy"),("John","Liza"),("Julia","Lucy"),("Liza","Bob"),("Liza","Frank")]
> transitiveClusureOfGraph someTallerThan
> fromList [("Alexandre","Andrea"),("Alexandre","Bob"),("Alexandre","Frank"),("Alexandre","John"),("Alexandre","Liza"),("Andrea","Bob"),("Andrea","Frank"),("Andrea","John"),("Andrea","Liza"),("George","Frank"),("George","Lucy"),("John","Bob"),("John","Frank"),("John","Liza"),("Julia","Lucy"),("Liza","Bob"),("Liza","Frank")]
a `isTallerThan` b = (a,b) `isMemberOfTransitiveGraph` someTallerThan
> "Alexandre" `isTallerThan` "Frank"
> T
> "Frank" `isTallerThan` "Alexandre"
> F
> "Alexandre" `isTallerThan` "George"
> U
> "George" `isTallerThan` "Alexandre"
> U
**
EXAMPLE 3
**
incomeIsLessOrEqualThan = S.fromList [("Bob","Liza"),("Liza","Tom"),("Tom","Bob"),("Tom","Mary"), ("Tom","Tom")]
> S.filter (\(a,b) -> a /= b) $ transitiveClusureOfGraph incomeIsLessOrEqualThan
> fromList [("Bob","Liza"),("Bob","Mary"),("Bob","Tom"),("Liza","Bob"),("Liza","Mary"),("Liza","Tom"),("Tom","Bob"),("Tom","Liza"),("Tom","Mary")]
Some comments:
Some ideas for Quickcheck tests:
Create a random connected graph and verify that every pair of points is in the transitive closure.
Verify that for any random graph the transitive closure of the transitive closure is just the same as doing the transitive closure just once.
Verify that your code returns the same answer as another implementation (such as from the fgl library.)
However, when I look at the fgl library I see that they just use a fixed graph to test their path query functions. Then they know exactly what the answers should be for all the tests.
Another idea is to solve an ACM (programming competition) problem which involves finding the transitive closure of a graph, and use your code in that solution. Both Timus and codeforces accept Haskell programs.
In isMemberOfTransitiveGraph you have the common sub-expression transitiveClusureOfGraph gr. Now GHC could (and should) detect this and factor it out so that it doesn't get evaluated twice, but it doesn't always do that. Moreover, being an interpreter, ghci won't perform common sub-expression elimination. So, given that transitiveClusureOfGraph is an expensive operation, you should write this function like
this:
isMemberOfTransitiveGraph (x,y) gr
| S.member (x,y) closure = T
| S.member (y,x) closure = F
| otherwise = U
where
closure = transitiveClusureOfGraph gr in
Also, computing the transitive closure for the entire graph is
an expensive way to determine if a specific pair is in the closure.
A better way to implement isMemberOfTransitiveClosure is to simply
perform a depth-first search start at one member of the pair until you a) either find the other element or b) fill out the connected component without finding the other element. Otherwise you are performing a lot of work on the other connected components which is irrelevant to the question you are trying to answer.
If you are really concerned about efficiency, restrict your node type to Int and use Data.IntSet or even Data.BitSet for sets of nodes.
When I have the two functions:
a)
three :: Int -> Maybe Int
three a
| a == 3 = Just 3
| otherwise = Nothing
b)
takeOne :: Int -> Int
takeOne a = (a - 1)
how do I call function a as a parameter to function b? i.e How do I let function b accept a 'Maybe Int' in place of an 'Int'?
At the minute when I try
takeOne (three 3)
I get the error:
ERROR - Type error in application
*** Expression : takeThree (three 3)
*** Term : three 3
*** Type : Maybe Int
*** Does not match : Int
Thanks.
You've got a few options, but I'd say the easiest is fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
Example:
> fmap takeOne $ three 3
Just 2
> fmap takeOne $ three 2
Nothing
Another option would be to use the function maybe, which takes a default value, a function to apply to any value inside the Just, and then the Maybe a to apply this to. An example should make it clear
> maybe 0 takeOne $ three 3
2
> maybe 0 takeOne $ three 2
0
Another alternative if you just want to give a default value is to use the function fromMaybe from Data.Maybe:
> import Data.Maybe
> fromMaybe 0 $ three 3
3
> fromMaybe 0 $ three 2
0
In Haskell, there is a typeclass called Functor defined as
class Functor f where
fmap :: (a -> b) -> f a -> f b
There are many, many types that are instances of Functor. In fact, all parametrized data structures are Functors, as are all Applicatives and Monads. The easiest mental model of a Functor is that it's just a fancy name for a container. For lists, fmap = map, for example. All it does is map a function over the elements inside a container.
Some more examples are:
> fmap (+1) (Left "error")
Left "error"
> fmap (+1) (Right 1)
Right 2
> x <- fmap (++", world") getLine
Hello
> x
Hello, world
> fmap (+1) [1..5]
[2,3,4,5,6]
> fmap (+1) ("fst", 2)
("fst", 3)
Even functions are Functors! Here fmap = (.), it's just normal function composition:
> let lengthPlusOne = fmap (+1) length
> lengthPlusOne "Hello"
6
One other option of course is to write your own.
data IAcceptedAMaybeInt = GotAnswer Int | NothingAtTheMoment deriving Show
pleaseAcceptAMaybeInt f g a = case g a of
Just b -> GotAnswer (f b)
otherwise -> NothingAtTheMoment
Output:
*Main> pleaseAcceptAMaybeInt takeOne three 3
GotAnswer 2
*Main> pleaseAcceptAMaybeInt takeOne three 2
NothingAtTheMoment
i have given two points.
Now of i need to check if those points are identical, so i do:
type datatypePoint = (Float,Float)
anyLine :: datatypePoint -> datatypePoint -> datatypeLine
anyLine a b = [[fst a, fst b] , [snd a, snd b]]
| (fst a == fst b) && (snd a == snd b) = error "Identical"
| otherwise = error "Not identical"
But i get error:
unexpected |
anybody could tell me why? What am i doing wrong?
You have a few errors here, first off, all types start with upper case letters in Haskell
type Point = (Float,Float)
anyLine :: Point -> Point -> Point
Next, pattern matching happens before the = sign.
anyLine (a1, a2) (b1, b2)
| a1 == b1 && a2 == b2 = error "Identical"
| otherwise = error "Not identical"
And with guards we omit the equality sign.
This could also just be
anyLine a b
| a == b = ...
| otherwise = ...
I think it's well worth the time to read a good Haskell tutorial to learn some of the basic concepts you're missing, I personally favor Learn You A Haskell.
You can specify a result or define cases; you can't do both at the same time.
anyLine :: datatypePoint -> datatypePoint -> datatypeLine
anyLine a b
| (fst a == fst b) && (snd a == snd b) = error "Identical"
| otherwise = error "Not identical"
Other folks have already answered the question, but I wanted to point out that this would be even simpler if you used "newtype" and "deriving"
newtype Point a = Point (a, a) deriving (Eq)
anyLine a b
| a == b = ....
| otherwise = ....
It also doesn't hurt to keep the type a generic, so now this will work for "Point"s of Floats, Ints, etc.
I just started learning Haskell. I think I've got the basics down, but I want to make sure I'm actually forcing myself to think functionally too.
data Dir = Right | Left | Front | Back | Up | Down deriving (Show, Eq, Enum)
inv Right = Left
inv Front = Back
inv Up = Down
Anyway, the jist of what I'm trying to do is to create a function to map between each "Dir" and its opposite/inv. I know I could easily continue this for another 3 lines, but I can't help but wonder if there's a better way. I tried adding:
inv a = b where inv b = a
but apparently you can't do that. So my question is: Is there either a way to generate the rest of the inverses or an altogether better way to create this function?
Thanks much.
If the pairing between Up and Down and so on is an important feature then maybe this knowledge should be reflected in the type.
data Axis = UpDown | LeftRight | FrontBack
data Sign = Positive | Negative
data Dir = Dir Axis Sign
inv is now easy.
Do you have a closed-form solution over the indices that corresponds to this function? If so, yes, you can use the Enum deriving to simplify things. For example,
import Prelude hiding (Either(..))
data Dir = Right
| Front
| Up
| Left
| Back
| Down
deriving (Show, Eq, Ord, Enum)
inv :: Dir -> Dir
inv x = toEnum ((3 + fromEnum x) `mod` 6)
Note, this relies on the ordering of the constructors!
*Main> inv Left
Right
*Main> inv Right
Left
*Main> inv Back
Front
*Main> inv Up
Down
This is very C-like, exploits the ordering of constructors, and is un-Haskelly. A compromise is to use more types, to define a mapping between the constructors and their mirrors, avoiding the use of arithmetic.
import Prelude hiding (Either(..))
data Dir = A NormalDir
| B MirrorDir
deriving Show
data NormalDir = Right | Front | Up
deriving (Show, Eq, Ord, Enum)
data MirrorDir = Left | Back | Down
deriving (Show, Eq, Ord, Enum)
inv :: Dir -> Dir
inv (A n) = B (toEnum (fromEnum n))
inv (B n) = A (toEnum (fromEnum n))
E.g.
*Main> inv (A Right)
B Left
*Main> inv (B Down)
A Up
So at least we didn't have to do arithmetic. And the types distinguish the mirror cases. However, this is very un-Haskelly. It is absolute fine to enumerate the cases! Others will have to read your code at some point...
pairs = ps ++ map swap ps where
ps = [(Right, Left), (Front, Back), (Up, Down)]
swap (a, b) = (b, a)
inv a = fromJust $ lookup a pairs
[Edit]
Or how about this?
inv a = head $ delete a $ head $ dropWhile (a `notElem`)
[[Right,Left],[Front,Back],[Up,Down]]
It is good to know, that Enumeration starts with zero.
Mnemonic: fmap fromEnum [False,True] == [0,1]
import Data.Bits(xor)
-- Enum: 0 1 2 3 4 5
data Dir = Right | Left | Front | Back | Up | Down
deriving (Read,Show,Eq,Ord,Enum,Bounded)
inv :: Dir -> Dir
inv = toEnum . xor 1 . fromEnum
I don't think I'd recommend this, but the simple answer in my mind would be to add this:
inv x = fromJust $ find ((==x) . inv) [Right, Front, Up]
I couldn't resist tweaking Landei's answer to fit my style; here's a similar and slightly-more-recommended solution that doesn't need the other definitions:
inv a = fromJust $ do pair <- find (a `elem`) invList
find (/= a) pair
where invList = [[Right, Left], [Up, Down], [Front, Back]]
It uses the Maybe monad.