Apply function to argument before performing pattern matching - haskell

I'm new to Haskell and trying to not instinctively think imperatively. I have a function which does all the work in a pattern matching block, however it needs to pattern match on the argument after a function is applied to it.
Doing this in a functional way gets me to this:
foo :: Int -> String
foo n = bar $ show n
bar :: String -> String
bar [] = ""
bar (c:s) = "-" ++ bar s
Where foo is the function I'm trying to implement but bar is where all the work gets done. foo only exists to provide the right type signature and perform the precursor show transformation before calling bar. In practice, bar could get quite complicated, but still, I have no reason to expose it as a separate function.
What's the Haskell way to perform a simple function like show and "then" pattern match on the result of that?
I tried changing the pattern matching to a case statement, but it didn't permit the all-important recursion, because there was no function to call recursively. For the same reason, using a where clause applied to multiple patterns also doesn't work.

I remembered that Learn You A Haskell often seemed to emphasise that where and let are more powerful than they first seem because "everything is a function" and the clauses are expressions themselves.
That prompted me to see if I could push where a bit harder and use it to essentially define the helper function bar. Turns out I can:
foo :: Int -> String
foo n = bar $ show n
where bar [] = ""
bar (c:s) = "-" ++ bar s
Unless there's a better way, I think this is the solution I'm after. It took a bit of beating back my imperative tendencies to see this, but it's starting to look logical and much more "core" than I was imagining.
Please provide an alternative answer if these assumptions are leading me off course!

It depends on whether the pattern-matching function is recursive or not.
In your example, it is called bar and is recursive.
foo :: Int -> String
foo n = bar $ show n
bar :: String -> String
bar [] = ""
bar (c:s) = "-" ++ bar s
Here, the (arguably) best solution is the one you found: use where (or let) and define it locally to foo:
foo :: Int -> String
foo n = bar $ show n
where
bar :: String -> String -- optional type annotation
bar [] = ""
bar (c:s) = "-" ++ bar s
The type annotation for the inner function is optional. Many Haskellers think that the top-level function foo should have its signature (and GHC with -Wall warns if you do not provide it) but also believe that the inner function do not have to be annotated. For what it is worth, I like to add it when I think it's non obvious from the context. Feel free to include or omit it.
When bar is not recursive, we have other options. Consider this code:
foo :: Int -> String
foo n = bar $ show n
bar :: String -> String
bar [] = "empty"
bar (c:s) = "nonempty " ++ c : s
Here, we can use case of:
foo :: Int -> String
foo n = case show n of
[] -> "empty"
(c:s) -> "nonempty " ++ c : s
This calls function show first, and then pattern-matches its result. I think this is easier to read than adding a where to define bar.
Theoretically, speaking, we could follow the case approach even in the recursive case, and leverage fix (a function from the library) to close the recursion. I do not recommend you to do this, since defining bar using where (or let) is more readable. I'm adding this less readable option here only for the sake of completeness.
foo :: Int -> String
foo n = fix (\bar x -> case x of
[] -> ""
(c:s) -> "-" ++ bar s
) $ show n
This is equivalent to the first recursive code snippet, but it requires much more time to read. The helper fix has its uses, but if I read this in actual production code I'd think the programmer is trying to show they are "clever" instead of writing simple, readable code.

Related

How to read the syntax `Typ{..}` in haskell? [duplicate]

This question already has an answer here:
pattern matching of the form: Option{..} <-
(1 answer)
Closed 4 years ago.
While reading library code here I have noticed a really weird looking syntax that I can't make sense of:
momenta
:: (KnownNat m, KnownNat n)
=> System m n
-> Config n
-> R n
momenta Sys{..} Cfg{..} = tr j #> diag _sysInertia #> j #> cfgVelocities
-- ^^^^^^^^^^^^^^^ the syntax in question
where
j = _sysJacobian cfgPositions
The relevant definitions of System includes a record { _sysJacobian :: R n -> L m n }, and { cfgVelocities :: R n } is part of the record declaration of Config so I believe I know what the code does, I think the code is quite readable, props to the author.
The question is: what is this syntax called and how exactly can I use it?
In short: it is an extension of GHC called RecordWildCards.
In Haskell you can use record syntax to define data types. For example:
data Foo = Bar { foo :: Int, bar :: String } | Qux { foo :: Int, qux :: Int }
We can then pattern match on the data constructor, and match zero or more parameters, for example:
someFunction :: Int -> Foo -> Foo
someFunction dd (Bar {foo=x}) = dd + x
someFunction dd (Qux {foo=x, qux=y}) = dd + x + y
But it can happen that we need access to a large amount (or even all) parameters. Like for example:
someOtherFunction :: Foo -> Int
someOtherFunction (Bar {foo=foo, bar=bar}) = foo
someOtherFunction (Qux {foo=foo, qux=qux}) = foo + qux
In case the number of parameters is rather large, then this becomes cumbersome. There is an extension RecordWildCards:
{-# LANGUAGE RecordWildCards #-}
this will implicitly write for every parameter foo, foo=foo if you write {..} when we do record pattern matching.
So we can then write:
someOtherFunction :: Foo -> Int
someOtherFunction (Bar {..}) = foo
someOtherFunction (Qux {..}) = foo + qux
So here the compiler implicitly pattern matched all parameters with a variable with the same name, such that we can access those parameters without explicit pattern matching, nor by using getters.
The advantage is thus that we save a lot on large code chunks that have to be written manually. A downside is however the fact that the parameters are no longer explicitly and hence the code is harder to understand. We see the use of parameters for which there exist actually getter counterparts, and thus it can introduce some confusion.
Like #leftroundabout says, probably lenses can do the trick as well, and it will prevent introducing variables that basically shadow getters, etc.
You can also merge the RecordWildCards with pattern matching on parameters, for example:
someOtherFunction :: Foo -> Int
someOtherFunction (Bar {bar=[], ..}) = foo
someOtherFunction (Bar {..}) = foo + 42
someOtherFunction (Qux {..}) = foo + qux
So here in case the bar parameter of a Foo instance with a Bar data constructor is the empty string, we return the foo value, otherwise we add 42 to it.
It's the RecordWildCards syntax extension. From the docs:
For records with many fields, it can be tiresome to write out each field individually in a record pattern ... Record wildcard syntax permits a ".." in a record pattern, where each elided field f is replaced by the pattern f = f ... The expansion is purely syntactic, so the record wildcard expression refers to the nearest enclosing variables that are spelled the same as the omitted field names.
Basically it brings the fields of a record into scope.
It is particularly useful when writing encoders/decoders (e.g. Aeson), but should be used sparingly in the interest of code clarity.

Different numbers of arguments when pattern matching Maybe

I've run into a problem I don't really understand. I thought that I would be able to write code like this in Haskell:
foo :: Maybe Int -> Int
foo Nothing = 0
foo Just x = x
But when I try to compile it, I get the error:
Equations for ‘foo’ have different numbers of arguments
I can fix it by changing my code to the following:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x
Which makes me think that GHC is interpreting Just as an argument to foo. But Haskell forbids using uppercase letters to start variable names, so I wouldn't think there should be any ambiguity here. What's going on?
You're correct, there's not ambiguity about whether or not Just is a constructor – but constructors can have no arguments! Haskell's pattern matching doesn't look up the names involved, it's strictly syntactic, and foo Just x = x is a perfectly well-formed function definition clause. It's ill-typed:
Prelude> let foo Just x = x
<interactive>:2:9:
Constructor ‘Just’ should have 1 argument, but has been given none
In the pattern: Just
In an equation for ‘foo’: foo Just x = x
but with different data types around, it'd be fine:
Prelude> data Justice = Just
Prelude> let foo Just x = x
Prelude> :t foo
foo :: Justice -> t -> t
Prelude> foo Just ()
()
Just could be a nullary constructor (as in the second example), and since function application is left-associative, the compiler parses Just and x as separate arguments and you get the "different numbers of arguments" error. (And as you can see above, if there weren't the Nothing case, you'd actually get the type error for code of that form.)
The idea is that pattern syntax should mirror application syntax. If I was calling foo I couldn't write foo Just x, because that means something else (and if foo had type (Int -> Maybe Int) -> Int -> Int then it would even work). Having patterns have different rules for where parentheses are needed than expressions would be very weird.
Writing compound patterns without parentheses and trusting the compiler to automatically group things also falls apart in more complex situations. What should this mean?
foo Just x : xs = ...

Pattern matching against record syntax

Consider the following data definition:
data Foo = A{field::Int}
| B{field::Int}
| C
| D
Now let's say we want to write a function that takes a Foo and increases field if it exists, and leave it unchanged otherwise:
incFoo :: Foo -> Foo
incFoo A{field=n} = A{field=n+1}
incFoo B{field=n} = B{field=n+1}
incFoo x = x
This naive approach leads to some code duplication. But the fact that both A and B shares field allows us to rewrite it:
incFoo :: Foo -> Foo
incFoo x | hasField x, n <- field x = x{field=n+1}
incFoo x = x
hasField A{} = True
hasField B{} = True
hasField _ = False
Less elegant, but that's defiantly easier to maintain when the actual manipulation is complex. The key feature here is x{field=n+1} - record syntax allows us to "update" field without specifying x's type. Considering this, I'd expect something similar to the following syntax (which is not supported):
incFoo :: Foo -> Foo
incFoo x{field=n} = x{field=n+1}
incFoo x = x
I've considered using View Patterns, but since field is a partial function (field C raises an error) it'll require wrapping it in more boilerplate code.
So my question is: why there's no support for the above syntax, and is there any elegant way of implementing a similar behavior?
Thanks!
The reason why you can't do this is because in Haskell, records are inherently second class. They always must be wrapped in a constructor. So in order to have this work as intended you either must use an individual case for each constructor, or use a record substitute.
One possible solution is to use lenses. I'll use the implementation of lenses lens since lens-family-th doesn't seem to handle duplicate field names.
import Control.Lens
data Foo = A {_f :: Int}
| B {_f :: Int}
deriving Show
makeLenses ''Foo
foo :: Foo -> Foo
foo = f %~ (+1)
And then we can use it like this
> foo (A 1)
A{_f = 1}

Generate new test data inside QuickCheck property

I'm having trouble with a programming problem here. Half the trouble is that the problem itself is quite tricky to think about, and the other half is that I can't remember how to find my way around QuickCheck.
I know that if you write a function that takes several arguments that have an Arbitrary instance, QuickCheck will let you use that method as a test. What I can't figure out is how to generate new test arguments inside that method. I want to write something like
prop13 :: Foo -> Bar -> Bool
prop13 foo bar =
if foobar foo bar
then fn1 foo
else newInput $ \ baz -> fn2 foo bar baz
but I can't figure out how the hell to do that.
Actually, no, what I really want to write is
prop13 :: Foo -> Bar -> Property
prop13 foo bar =
if foobar foo bar
then label "foobar=YES" $ fn1 foo
else label "foobar=NO" $ newInput $ \ baz -> fn2 foo bar baz
just so I can check it isn't taking one branch 100% of the time or something ridiculous like that.
Actually, what would be great is if I could demand that baz has some particular property. I vaguely remember QuickCheck having a function somewhere to throw away inputs not satisfying a given condition. (The only problem being that it might take an unreasonably number of attempts to satisfy the condition...)
Is there a way to do this? I'm staring at the Haddock page, but I can't figure out how to get what I want...
A property may take the form
classify <condition> <string>$ <property>
For example,
prop_Insert x xs =
ordered xs ==>
classify (ordered (x:xs)) "at-head" $
classify (ordered (xs ++ [x])) "at-tail" $
ordered (insert x xs)
where types = x :: Int
Test cases satisfying the condition are assigned the classification
given, and the distribution of classifications is reported after
testing. In this case the result is
Main> quickCheck prop_Insert
OK, passed 100 tests. 58% at-head,
at-tail. 22% at-tail. 4% at-head.
Note that a test case may fall into more than one classification.
(from QuickCheck manual)
For demanding the particular property of the input data, you may add somePredicate data ==> before the test body, as it is shown in the snippet above. Another example:
prop_max xs = (not . null xs) ==> head (sort xs) == maximum xs
You're right, this combinator throws away inappropriate cases. If that's undesired, you can make a newtype wrapper over the input type and redefine the Arbitrary instance for it (see examples of Positive, NonEmpty and so on here)
I found the answer in another answer. Apparently it's forAll:
else forAll arbitrary $ \ baz -> fn2 foo bar baz
I just couldn't remember how to do it...
(This also has the nice feature of allowing me to specify a specific random data generator.)

Haskell data type function parameter

What is the significance of the parenthesis in a function definition in Haskell with respect to the data type of parameters.
For example:
doStuff Name -> Age -> String
doStuff (NameConstr a) (AgeConstr b) = "Nom: " ++ a ++ ", age: " ++ b
with the following defined somewhere beforehand:
data Name = NameConstr String
data Age = AgeConstr Integer
Could the function parameters a and b be captured in a way that negates the need for parenthesis here?
FYI, I'm working through:
http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-Way/#type-construction
http://learnyouahaskell.com/types-and-typeclasses ,
and I just can't seem grasp this finer detail yet.
Without parentheses, the function would be deemed to have four parameters. I can't think of a counterexample where omitting brackets would lead to ambiguity, though.
If you want, you can redefine your types as follows:
data Name = NameConstr { getName :: String }
data Age = AgeConstr { getAge :: Integer }
so that your function can become:
doStuff n a = "Nom: " ++ getName n ++ ", age: " ++ show (getAge a)
(fixed the last part; a is an Integer and cannot be concatenated to a string)
Indeed, it's possible to parse simple grammar for (even nested) patterns without parens at all. Suppose such one:
<PAT> ::= <WILDCARD> | <VAR> | <CON0> | <CON1> <PAT> | <CON2> <PAT> <PAT> ...
<VAR> ::= <LNAME>
<CON*> ::= <UNAME>
<WILD> ::= "_"
where LNAME is names that starts with lowercase letter and UNAME starts with uppercase letter. While parsing we should look up constructor name so we can find out its arity. Then we can parse constructor fields using arity information. But this lookup might significant complicate and slow down parsing itself. Haskell has much more complex patterns(view patterns, "as" patterns, records, infix constructors with arbitrary fixity, e.t.c.) and omitting parens can lead to ambiguity.
Though there is another reason not to do that. Consider the following code:
data Bar = Bar Int
data Foo = Foo Int
libFunction Foo a Bar b = a + b
someUse bar foo = libFunction foo bar
Next imagine we change datatypes a bit:
data Bar = Bar
data Foo = Foo Int Bar Int
Modified code might still typecheck, but the function will do not that we expect. Not a real world example but nevertheless. And since Haskell have type classes it can be pretty hard to find out where we get something wrong.
In other words: we can loose quality of error messages and parens defends us from unexpected behaviour after changes.
It's slightly silly, but in this case there is actually a way to avoid parentheses:
doStuff :: Name -> Age -> String
NameConstr a `doStuff` AgeConstr b = "Nom: " ++ a ++ ", age: " ++ b
This is exactly the same way you define an infix operator, and using backticks to infix-ify a non-operator identifier works just as well when defining it as when applying it.
I don't recommend actually doing this with functions you don't expect to be used in backtick-y infix style, though.

Resources