Is there a way to unblock Haskell?

I am writing a Haskell program. I created a datatype called dimension which is an array of doubles, it looks like this:

data Measurement = Measurement [Double]  deriving (Show)

      

I have a drop function in Measurement, it takes a list of doubling lists and feeds it to a measurement list. It looks like this:

castToMeasurement :: [[Double]] -> [Measurement]
castToMeasurement = map Measurement

      

But now I want to do some operations on double values. So is there a way I can deal with the array of doubles? So when I give it a Dimension (or a Dimension list), it translates it into a Duplicate list (or a list of doubles lists). Thank!

+3


source to share


4 answers


Yes there is:

data Measurement = Measurement { getMeasurement :: [Double] } deriving Show

castToMeasurement :: [[Double]] -> [Measurement]
castToMeasurement = map Measurement

castFromMeasurement :: [Measurement] -> [[Double]]
castFromMeasurement = map getMeasurement

      



Simple, isn't it?

+6


source


Well, no and yes.

The way you formulate the question, is there a way to "untie", the answer should be not, not at all. Suppose we have a list of strings:

example1 :: [String]
example1 = ["Hello", "cruel", "world"]

      

We can use map length

to map this to string lengths:

example2 :: [Int]
example2 = map length example
-- value: [5, 5, 5]

      



But there is no way to "unmount" the value example2

to get it back example1

. This would require that there be a function that, given the length, figure out which string the original list has, but that's clearly not enough information!

But this gives us a hint as to what situation we can do the "unmapping" you want. If the function we are initially mapped to has the opposite , then we can match that with the opposite to the "undo" effect map

. In your case, the constructor Measurement

has the inverse:

-- | The inverse of the 'Measurement' constructor.  Laws:
--
-- > Measurement (getMeasurement x) == x
-- > getMeasurement (Measurement xs) == xs
getMeasurement :: Measurement -> [Double]
getMeasurement (Measurement xs) = xs

      

Since Measurement

and getMeasurement

are inverse, it also follows that map Measurement

and map getMeasurement

, and so:

map getMeasurement (map Measurement xs) == xs
map Measurement (map getMeasurement xs) == xs

      

+6


source


Sure. Here you can learn more about it.

Think about a function f

:

f :: [Double] -> Measurement
f list = Measurement list

      

It just terminates the constructor Measurement

. I use the new function because it is much easier for me to think about the function than the constructors.

Now you need a reverse function for f

:

g :: Measurement -> [Double]
g (Measurement list) = list

      

So now you can build a function:

castFromMeasurement :: [Measurement] -> [[Double]]
castFromMeasurement = map g

      

It looks a little ugly. Therefore, we can change it using lambdas:

castFromMeasurement :: [Measurement] -> [[Double]]
castFromMeasurement = map (\(Measurement list) -> list)

      

But note that it only works when your data type is not abstract (you have full constructor access). Also you can override your data like this:

data Measurement = Measurement { getMeasurement :: [Double] } deriving Show

      

In this case, you already have a function g = getMeasurement

. So castFromMeasurement

it looks like this:

castFromMeasurement :: [Measurement] -> [[Double]]
castFromMeasurement = map getMeasurement

      


More generally, you can unmap

if and only if the function f

you used to display is reversible.

+4


source


You have the answer to your question, but let him bring the math to the table and find out when and how to undo it.

We are pure functional programmers; this means that the functions we write are very mathematical (which is not much for many reasons, one of them: you can write this answer). When working with functions, the domain of functions is any possible value of the input type (+ bottom for nested types). The range, as well as all possible values ​​of the output type.

What you are basically asking for is the inverse function for the function in your example ( fmap Measurement

).
A function inverse for a function will "undo" what that function has "done".
If I have a value x

and a function f

, and the inverse function f

is equal g

, then by definition x = f(g(x))) = g(f(x)))

. This is probably gibberish, so think about the functions f = (+1)

and g = subtract 1

and pick any integer for x

. Let's say, for example x=5

. f(5) = 6

and now notice how when applying g

- g(6) = 5

- you got the number you started with.
You are "frustrated" f

applying the result to g

because it g

is an inverse f

.

Some functions do not have an inverse function (as Luis Casillas said in his answer ).
When your function is actually there, you can find it. If it really is possible, it is usually as complex as the function you are calling (for example, as above, plus becomes minus. As in your example - your function was simple, so the reverse should have been simple as well).

An easy way to determine if there is an inverse function is to see if there is a one- to -one mapping between domain and range. If not, you lost data when you applied this function and you cannot go back. So if the reverse function doesn't exist and you need to return anyway, you must find other means. For example. zip the original value before start ( (x, f x)

), and to get the original value just apply fst

.

Inverse functions on Khan Academy
Inverse functions on TheMathPage
Inverse functions on Wikipedia

+3


source







All Articles