Syntax of where block - haskell

I'm reading Programming in Haskell by Graham Hutton and it gives the following code in Chapter 13:
import Control.Applicative
import Data.Char
{- some code omitted -}
newtype Parser a = P (String -> [(a, String)])
item :: Parser Char
item = P (\ input -> case input of
[] -> []
x:xs -> [(x,xs)])
three :: Parser (Char,Char)
three = pure g <*> item <*> item <*> item
where g a b c = (a,c)
I'm having a hard time understanding the last line
where g a b c = (a,c)
I understand that this line exists because three has type Parser(Char, Char) but what does g a b c represent? How is g a b c syntactically valid? I'm used to seeing where in cases like
f :: s -> (a,s)
f x = y
where y = ... x ...
where each symbol x and y appear before the where declaration.

It is the syntax to declare a function. It is the equivalent to
where g = \a b c -> (a,c)
g is a function which takes 3 arguments and returns a tuple

How is g a b c syntactically valid?
It's valid for the same reason same definition on the top-level of the module would be valid. The difference between definitions in where and top level is just that you have variables bound in function's head (e.g. x in your last example) in scope and can use them on the right side, but this doesn't mean you have to use them.

Related

Repetitions as an Hylomorphism

So I've been trying to convert this Haskell function thats checks if a list doesn't have any repetitions into an Hylomorphism, but there's something odd about it.
valid :: [a] -> Bool
valid [] = True
valid (h:t) = if (not (elem h t)) then valid t else False
I'll be glad if anyone can help! Thx
Well a hylomoprhism is a function h : A &rightarrow; C that can be defined in an anamoprhism (g and p) and catamorphism (c and ⊕) part.
The anamorphism part consists of a function g : A &rightarrow; B × A that "unfolds" the object into smaller parts, and p : A &rightarrow; Bool a predicate that determines if we are done unfolding.
The catamorphism part consists of a value c &in; C and an operator ⊕ : B × C &rightarrow; C.
(this text is a slightly modified version of the Wikipedia page)
In your case the unfolding means that we unfold a list in some value (of type B, and a recursive part, that is here the tail of the list.
The predicate p can be derived out of your definition: if the list is empty, then we have terminated. It is clear that in that case we return True, so that means c is True.
So now what would the B part be? Well if we look at your function we need access to both the head and the tail of the list, so B can be seen as a 2-tuple containing the head (as first element), and a tail (as second element).
So now the remaining question is what ⊕ does? It takes as input a 2-tuple of type E×[E] (pseudo-Haskell notation), and a boolean (type C which is a Bool). As we can see, it checks if the head is en element of the tail. If that is the case, it returns False, and ignores the recursive part, otherwise it returns the recursive part.
So we can write this in Haskell like:
-- types
type A e = [e]
type B e = (e, [e])
type C = Bool
-- functions
p :: A e -> Bool
p [] = True
p (_:_) = False
g :: A e -> (B e, A e)
g (h:t) = ((h, t), t)
c :: C
c = True
plus :: Eq e => B e -> C -> C
plus (h, t) r | elem h t = False
| otherwise = r
hylo :: Eq e => A e -> C
hylo a | p a = c
| otherwise = plus b (hylo a')
where (b, a') = g a
hylo is thus a straighforward implementation based on the definition where we thus take the functions p, c, plus and g as "building blocks".

Anamorphism in Banana, Lenses and Barbed wires

Shouldn't
g a = (a,a)
in the definition of anamorphism for iterate in here? I find that, f is not applied for the zip case. Or am I reading it wrong?
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.41.125&rep=rep1&type=pdf
No, g a = (a, f a) is the correct definition. I'm not sure I understand your objection about zip; the two functions iterate and zip are not really related. They are both implemented as anamorphisms in this paper, but the similarities basically end there -- and they don't share any code other than the definition of an anamorphism.
You can verify that these definitions are correct yourself by transcribing his math to Haskell:
import Prelude hiding (iterate)
anamorphism g p b | p b = []
| otherwise = a : anamorphism g p b'
where (a, b') = g b
iterate f = anamorphism g (const False)
where g a = (a, f a)
Then, in ghci:
> take 10 (iterate succ 0)
[0,1,2,3,4,5,6,7,8,9]
This jives with the built-in:
> take 10 (Prelude.iterate succ 0)
[0,1,2,3,4,5,6,7,8,9]

Trouble explaining Haskell code with where and pattern match

I have hard time parsing how mf m y are assigned values or even why there can be 3 variables on the left side of assignment in where section.
Q: Can anyone explain what happens here in both cases? (that is for empty list and a list with some elements)
-- | A variant of 'foldl' that has no base case,
-- and thus may only be applied to non-empty structures.
--
-- #'foldl1' f = 'List.foldl1' f . 'toList'#
foldl1 :: (a -> a -> a) -> t a -> a
foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")
(foldl mf Nothing xs)
where
mf m y = Just (case m of
Nothing -> y
Just x -> f x y)
(this is the source code for the foldl1 function).
Definitions in where clauses follow the same syntax as global definitions, so mf m y = ... defines a function named mf, which takes parameters named m and y.
I have hard time parsing how mf m y are assigned values or even why there can be 3 variables.
You do not define three variables here: you define a variable mf which is a function, and m and y are two arguments of the function mf.
We can make the function more elegant, and thus omit the m and y. mf can be defined as:
mf Nothing = Just . id
mf (Just x) = Just . f x
Mind that we can not simply make mf an outer function, since it uses a function f, with is a parameter of foldl1. So we put it in a where clause:
foldl1 :: (a -> a -> a) -> t a -> a
foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")
(foldl mf Nothing xs)
where mf Nothing = Just . id
mf (Just x) = Just . f x
In the empty list case, foldl mf Nothing [] ~ Nothing by definition, so foldl1 will return the "empty structure" error.
When xs is not empty, then foldl1' is simply a left fold by foldl. In this case foldl has the type
foldl :: (Maybe a -> a -> Maybe a) -> Maybe a -> [a] -> Maybe a
which makes use of the combining function mf :: Maybe a -> a -> Maybe a defined in the where clause.

Haskell pattern matching inside parentheses

I would like to define a function that operates on an expression of a certain type, but has access to its internal structure, if it has one. For instance, f in what follows:
g :: a -> a -> a
g x y = y
f :: a -> a
f x'#(g x y) = x'
f _ = 1
(g x y) is of type a, so f should be able to take it as an argument, but the definition for f above can't be parsed by Haskell. I would like to define something like f to take advantage of call-by-name evaluation. Is there any way to do this in Haskell?
First, pattern matching is allowed only on patterns, i.e. expressions built from application, constructors, and variables (used at most once).
Second, even if it were extended, your example is problematic because your g is not injective:
case g x y of g a b -> a
should be equal to, since g x y = y
case y of g a b -> a
but then a could be anything.
If instead it happens that g is defined by an expression which could be a pattern, then GHC can allow using it as a pattern if you ask for it through the PatternSynonyms GHC extension.
pattern G a b = ("hello", b, a)
foo = case someTriple of
G a b -> use a b
(s, x, y) -> ...
bar = G 4 5 -- we can also use G as a function

Writing in pointfree style f x = g x x

I am learning Haskell. I'm sorry for asking a very basic question but I cant seem to find the answer. I have a function f defined by :
f x = g x x
where g is an already defined function of 2 arguments. How do I write this pointfree style?
Edit : without using a lambda expression.
Thanks
f can be written with Control.Monad.join:
f = join g
join on the function monad is one of the primitives used when constructing point-free expressions, as it cannot be defined in a point-free style itself (its SKI calculus equivalent, SII — ap id id in Haskell — doesn't type).
This is known as "W" combinator:
import Control.Monad
import Control.Monad.Instances
import Control.Applicative
f = join g -- = Wg (also, join = (id =<<))
= (g `ap` id) -- \x -> g x (id x) = SgI
= (<*> id) g -- = CSIg
= g =<< id -- \x -> g (id x) x
= id =<< g -- \x -> id (g x) x
S,K,I are one basic set of combinators; B,C,K,W are another - you've got to stop somewhere (re: your "no lambda expression" comment):
_B = (.) -- _B f g x = f (g x) = S(KS)K
_C = flip -- _C f x y = f y x = S(S(K(S(KS)K))S)(KK)
_K = const -- _K x y = x
_W = join -- _W f x = f x x = CSI = SS(KI) = SS(SK)
_S = ap -- _S f g x = f x (g x) = B(B(BW)C)(BB) = B(BW)(BBC)
= (<*>) -- from Control.Applicative
_I = id -- _I x = x = WK = SKK = SKS = SK(...)
{-
Wgx = gxx
= SgIx = CSIgx
= Sg(KIg)x = SS(KI)gx
= gx(Kx(gx)) = gx(SKgx) = Sg(SKg)x = SS(SK)gx
-- _W (,) 5 = (5,5)
-- _S _I _I x = x x = _omega x -- self-application, untypeable
-}
I got here by pure chance, and I want to offer my solution, as nobody has mentioned lifting yet in this thread, not explicitly at least.
This is a solution:
f = liftM2 g id id
How to look at it?
g has type a -> a -> b, i.e. it takes two values of some type (the same type for both, otherwise the definition the OP gave of f wouldn't make sense), and gives back another value of some type (not necessarily of the same type as the arguments);
lift2M g is the lifted version of g and it has type (Monad m) => m a -> m a -> m b: it takes two monadic values, which are each a value in a so-far-unspecified context, and gives back a monadic value;
when passing two functions to liftM2 g, the die is cast on what the context of the Monad is: it is that the values are not in there yet, but will eventually be, when the function will receive the arguments it needs; in other words, functions are monads that store their own future values; therefore, lift2M g takes in input two functions (or, the future values of two functions), and gives back the another function (or, its future value); knowing this, its type is the same as above if you change m to (->) r, or r ->: (r -> a) -> (r -> a) -> (r -> b)
the two functions that we pass are both id, which promises it'll give back the same value it receives;
liftM2 g id id is therefore a function of type r -> b that passes its argument to those two ids, which let it unchanged and forward it to g.
In a similar fashion, one can exploit that functions are applicative functors, and use this solution:
f = g <$> id <*> id

Resources