sqd
sqd

Reputation: 1535

Haskell: Why can't I pattern match against function?

Such as:

extract (f x) = x

What I want to do is to extract the parameter from a function or a type constructor, such as

extract succ 4 = 4
extract Just 4 = 4

ps. extract (f x) = f doesn't work either.

Upvotes: 1

Views: 170

Answers (3)

chi
chi

Reputation: 116139

The "extracting the argument from a function" would require to invert said function, which is possible only if the function is injective. More to the point, assume

square x = x*x

and

root (square x) = x   -- assume it works, somehow

We should have

root (square 2)    = 2
root (square (-2)) = -2
root 4             = ???

The last 4 is both the square of 2 and -2, and there's no single result we can associate to it. The square function is not injective, so its inverse is not even a function.

Worse, since 4 is equal to both the squares above, referential transparency mandates that the two lines above return the same result. This can not be the case, though.

Upvotes: 4

rafalio
rafalio

Reputation: 3946

You definitely can pattern match against the structure of your data with a data constructor, like your example, Just. What you need is to wrap it in parentheses, (Just 4), otherwise your extract function looks like it would be taking a data constructor, and not a constructed value.

In your case, you would want:

extract (Just x) = x

That's, in fact, part of the fromJust function.

The other answer explains why you can't match against function application. To that, I'll add that it would be kind of like a magic way to get an inverse function. If there was an extract (f x) = x, it would be like magically having a g such that g . f = id. In your case, you defined a function succ which I presume would be

succ x = x+1

Now, if extract (succ x) = x was possible, because of equational reasoning, extract would of type Integer -> Integer and you would magically have constructed the inverse of succ, x-1.

What is possible though, like I showed above, is matching against the structure of data.

You can define, instead of a function succ working on Integers, a new datatype:

data Nat = Zero | Succ Nat

And then easily have an extract function:

extra Zero = Zero
extract (Succ x) = x

Just remember that you can, and are in fact encouraged to, to pattern match against things like (Just x).

Upvotes: 1

dfeuer
dfeuer

Reputation: 48580

One of the key concepts in functional programming, and especially pure functional programming, is equational reasoning. The = in Haskell is actual equality (leaving aside order of pattern matching and such). So when we write

f 3 = 12

that means f 3 and 12 are actually the same thing—completely indistinguishable. Since extract 12 doesn't make any sense, neither does extract (f 3).

To come at it from another direction, at run-time, there is no way to tell that a certain value was formed by applying a certain function to a certain other value. Making such information available would generally be very expensive, and would not often be useful.

Upvotes: 6

Related Questions