Pattern matching over Data.Map - haskell

I did a search but, surprisingly, didn't find anything that would help me to perform pattern matching over it. I need to make sure that in my Map "variable" exactly 3 keys. That's it. Instead of "if ... then ... else", I want to go with pattern matching as it is easier to read and seems to be more haskell way. So:
myFunction :: Map String String
--.......................
main = do
let var1 = myFunction
-- how do I ensure it has exactly 3 keys in it and if not raise an error?

You cannot pattern match on abstract data types, as you don’t have access to their constructors¹, so you will have to work with the functions provided by the `Data.Map´ module.
But note that there is a size :: Map k a -> Int function you can use. And if you don’t like if .. then .. else .. (which is in no way wrong or unhaskellish), you can use pattern guards:
foo m | size m == 3 = ...
| otherwise = error "Not three element"
¹ Disregarding view patterns and pattern synonyms here, but these are just syntactic surgar.

You could pattern match on M.toList:
import qualified Data.Map as M
-- ...
main = do
case (M.toList myFunction) of
[a,b,c] -> ... -- exactly 3 arguments
_ -> ... -- more or less than 3 arguments

Related

Pattern matching on function application in a pattern match?

I'd like to pattern match against a value returned from function application. For instance:
If I have a Map and I'd like to alternate on a key being in that map, do I have a better option than:
f map k = case map !? k of
Just _ -> foo
Nothing -> bar
In this particular case I could just as easily use member and guard, like:
f map k | member k map = foo
| otherwise = bar
but would prefer to use pattern matching in some cases.
Your first example does use pattern matching, but just in a case expression. But I think what you're looking for is the ViewPatterns extension, which can be useful for eliminating boilerplate (in particular in a case expression, where you can use both pattern matching and guards together).
{-# LANGUAGE ViewPatterns #-}
f k ((!? k)-> Just _) = foo
f _ _ = bar
Notice though that you need to switch the order of the arguments in order for k to be in scope in the view pattern for the seconds argument.
But I don't think this is better than your first version of f.

Pattern matching in Haskell case statements

I came across the following piece of code:
lala :: [[Int]] -> Bool
lala b = case b of
(a:_) | Just (b, _) <- uncons a -> True
other -> False
While I understand that the function checks that the first element of the list is not empty (there are better ways of writing this, but that's not the point), I don't fully understand the pattern matching happening in the case statement. Is the left arrow in this case simply pattern matching on the uncons call? Can this style of pattern matching be nested? This almost seems like a list comprehension syntax, are there other places where this type of pattern matching can be used?

How to define multiple patterns in Frege?

I'm having some trouble defining a function in Frege that uses multiple patterns. Basically, I'm defining a mapping by iterating through a list of tuples. I've simplified it down to the following:
foo :: a -> [(a, b)] -> b
foo _ [] = [] --nothing found
foo bar (baz, zab):foobar
| bar == baz = zab
| otherwise = foo bar foobar
I get the following error:
E morse.fr:3: redefinition of `foo` introduced line 2
I've seen other examples like this that do use multiple patterns in a function definition, so I don't know what I'm doing wrong. Why am I getting an error here? I'm new to Frege (and new to Haskell), so there may be something simple I'm missing, but I really don't think this should be a problem.
I'm compiling with version 3.24-7.100.
This is a pure syntactical problem that affects newcomers to languages of the Haskell family. It won't take too long until you internalize the rule that function application has higher precedence than infix expression.
This has consequences:
Complex arguments of function application need parentheses.
In infix expressions, function applications on either side of the operator do not need parentheses (however, individual components of function application may still need them).
In Frege, in addition, the following rule holds:
The syntax of function application and infix expressions on the left hand side of a definition is identical to the one on the right hand side as far as lexemes allowed on both sides are concerned. (This holds in Haskell only when # and ~ are not used.)
This is so you can define an addition function like this:
data Number = Z | Succ Number
a + Z = a
a + Succ b = Succ a + b
Hence, when you apply this to your example, you see that syntactically, you're going to redefine the : operator. To achieve what you want, you need to write it thus:
foo bar ((baz, zab):foobar) = ....
-- ^ ^
This corresponds to the situation where you apply foo to a list you are constructing:
foo 42 (x:xs)
When you write
foo 42 x:xs
this means
(foo 42 x):xs

Haskell pattern matching symmetric cases

Suppose I have a haskell expression like:
foo (Nothing, Just a) = bar a
foo (Just a, Nothing) = bar a
Is there any haskell syntax to collapse those cases, so I can match either pattern and specify bar a as the response for both? Or is that about as succinct as I can get it?
If your code is more complex than your example, you might want to do something like this, using the Alternative instance for Maybe and the PatternGuards extension (part of Haskell2010).
{-# LANGUAGE PatternGuards #-}
import Control.Applicative
foo (x, y) | Just a <- y <|> x = bar a
In case you are not familiar with it, <|> picks the left-most Just if there is one and returns Nothing otherwise, causing the pattern guard to fail.
That's as succinct as it gets in Haskell. In ML there is a syntax for what you want (by writing multiple patterns, which bind the same variables, next to each other separated by | with the body after the last pattern), but in Haskell there is not.
You can use -XViewPatterns, to add arbitrary functions to collapse your two cases into a single pattern.
Your pattern is now a function p that yields the thing you want to match:
foo (p -> (Just a, Nothing)) = bar a
much simpler!
We have to define p though, as:
p (Nothing, a#(Just _)) = (a, Nothing)
p a#(Just _, Nothing) = a
p a = a
or however you wish to normalize the data before viewing.
References: The GHC User's Guide chapter on View Patterns

SML conversions to Haskell

A few basic questions, for converting SML code to Haskell.
1) I am used to having local embedded expressions in SML code, for example test expressions, prints, etc. which functions local tests and output when the code is loaded (evaluated).
In Haskell it seems that the only way to get results (evaluation) is to add code in a module, and then go to main in another module and add something to invoke and print results.
Is this right? in GHCi I can type expressions and see the results, but can this be automated?
Having to go to the top level main for each test evaluation seems inconvenient to me - maybe just need to shift my paradigm for laziness.
2) in SML I can do pattern matching and unification on a returned result, e.g.
val myTag(x) = somefunct(a,b,c);
and get the value of x after a match.
Can I do something similar in Haskell easily, without writing separate extraction functions?
3) How do I do a constructor with a tuple argument, i.e. uncurried.
in SML:
datatype Thing = Info of Int * Int;
but in Haskell, I tried;
data Thing = Info ( Int Int)
which fails. ("Int is applied to too many arguments in the type:A few Int Int")
The curried version works fine,
data Thing = Info Int Int
but I wanted un-curried.
Thanks.
This question is a bit unclear -- you're asking how to evaluate functions in Haskell?
If it is about inserting debug and tracing into pure code, this is typically only needed for debugging. To do this in Haskell, you can use Debug.Trace.trace, in the base package.
If you're concerned about calling functions, Haskell programs evaluate from main downwards, in dependency order. In GHCi you can, however, import modules and call any top-level function you wish.
You can return the original argument to a function, if you wish, by making it part of the function's result, e.g. with a tuple:
f x = (x, y)
where y = g a b c
Or do you mean to return either one value or another? Then using a tagged union (sum-type), such as Either:
f x = if x > 0 then Left x
else Right (g a b c)
How do I do a constructor with a tuple argument, i.e. uncurried in SML
Using the (,) constructor. E.g.
data T = T (Int, Int)
though more Haskell-like would be:
data T = T Int Bool
and those should probably be strict fields in practice:
data T = T !Int !Bool
Debug.Trace allows you to print debug messages inline. However, since these functions use unsafePerformIO, they might behave in unexpected ways compared to a call-by-value language like SML.
I think the # syntax is what you're looking for here:
data MyTag = MyTag Int Bool String
someFunct :: MyTag -> (MyTag, Int, Bool, String)
someFunct x#(MyTag a b c) = (x, a, b, c) -- x is bound to the entire argument
In Haskell, tuple types are separated by commas, e.g., (t1, t2), so what you want is:
data Thing = Info (Int, Int)
Reading the other answers, I think I can provide a few more example and one recommendation.
data ThreeConstructors = MyTag Int | YourTag (String,Double) | HerTag [Bool]
someFunct :: Char -> Char -> Char -> ThreeConstructors
MyTag x = someFunct 'a' 'b' 'c'
This is like the "let MyTag x = someFunct a b c" examples, but it is a the top level of the module.
As you have noticed, Haskell's top level can defined commands but there is no way to automatically run any code merely because your module has been imported by another module. This is entirely different from Scheme or SML. In Scheme the file is interpreted as being executed form-by-form, but Haskell's top level is only declarations. Thus Libraries cannot do normal things like run initialization code when loaded, they have to provide a "pleaseRunMe :: IO ()" kind of command to do any initialization.
As you point out this means running all the tests requires some boilerplate code to list them all. You can look under hackage's Testing group for libraries to help, such as test-framework-th.
For #2, yes, Haskell's pattern matching does the same thing. Both let and where do pattern matching. You can do
let MyTag x = someFunct a b c
in ...
or
...
where MyTag x = someFunct a b c

Resources