質問

I would like to create three Haskell functions: a, b, and c.

Each function is to have one argument. The argument is one of the three functions.

I would like function a to have this behavior:

  • if the argument is function a then return function a.
  • if the argument is function b then return function b.
  • if the argument is function c then return function a.

Here's a recap of the behavior I desire for function a:

a a = a
a b = c
a c = a 

And here's the behavior I desire for the other two functions:

b a = a
b b = a
b c = c

c a = c
c b = b
c c = c

Once created, I would like to be able to compose the functions in various ways, for example:

  a (c b)
= a (b)
= c

How do I create these functions?

役に立ちましたか?

解決

Since you have given no criteria for how you are going to observe the results, then a = b = c = id satisfies your criteria. But of course that is not what you want. But the idea is important: it doesn't just matter what behavior you want your functions to have, but how you are going to observe that behavior.

There is a most general model if you allow some freedom in the notation, and you get this by using an algebraic data type:

data F = A | B | C
    deriving (Eq, Show) -- ability to compare for equality and print

infixl 1 % 
(%) :: F -> F -> F
A % A = A
A % B = C
A % C = A
B % A = A
...

and so on. Instead of saying a b, you have to say A % B, but that is the only difference. You can compose them:

  A % (C % B)
= A % B
= B

and you can turn them into functions by partially applying (%):

a :: F -> F
a = (A %)

But you cannot compare this a, as ehird says. This model is equivalent to the one you specified, it just looks a little different.

他のヒント

This is impossible; you can't compare functions to each other, so there's no way to check if your argument is a, b, c or something else.

Indeed, it would be impossible for Haskell to let you check whether two functions are the same: since Haskell is referentially transparent, substituting two different implementations of the same function should have no effect. That is, as long as you give the same input for every output, the exact implementation of a function shouldn't matter, and although proving that \x -> x+x and \x -> x*2 are the same function is easy, it's undecidable in general.

Additionally, there's no possible type that a could have if it's to take itself as an argument (sure, id id types, but id can take anything as its first argument — which means it can't examine it in the way you want to).

If you're trying to achieve something with this (rather than just playing with it out of curiosity — which is fine, of course), then you'll have to do it some other way. It's difficult to say exactly what way that would be without concrete details.

Well, you can do it like this:

{-# LANGUAGE MagicHash #-}

import GHC.Prim
import Unsafe.Coerce

This function is from ehird's answer here:

equal :: a -> a -> Bool
equal x y = x `seq` y `seq`
              case reallyUnsafePtrEquality# x y of
                 1# -> True
                 _  -> False

Now, let's get to business. Notice that you need to coerce the arguments and the return values as there is no possible type these functions can really have, as ehird pointed out.

a,b,c :: x -> y
a x | unsafeCoerce x `equal` a = unsafeCoerce a
    | unsafeCoerce x `equal` b = unsafeCoerce c
    | unsafeCoerce x `equal` c = unsafeCoerce a

b x | unsafeCoerce x `equal` a = unsafeCoerce a
    | unsafeCoerce x `equal` b = unsafeCoerce a
    | unsafeCoerce x `equal` c = unsafeCoerce c

c x | unsafeCoerce x `equal` a = unsafeCoerce c
    | unsafeCoerce x `equal` b = unsafeCoerce b
    | unsafeCoerce x `equal` c = unsafeCoerce c

Finally, some tests:

test  = a (c b) `equal` c   -- Evaluates to True
test' = a (c b) `equal` a   -- Evaluates to False

Ehh...

As noted, functions can't be compared for equality. If you simply want functions that satisfy the algebraic laws in your specificiation, making them all equal to the identity function will do nicely.

I hope you are aware that if you post a homework-related question to Stack Overflow, the community expects you to identify it as such.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top