1

我想创建三个 Haskell 函数:abc

每个函数都有一个参数。参数是三个函数之一。

我希望函数a具有这种行为:

  • 如果参数是函数a,则返回函数a
  • 如果参数是函数 b 则返回函数b
  • 如果参数是函数 c 则返回函数a

以下是我对功能期望的行为的回顾a

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

这是我希望其他两个功能的行为:

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

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

创建后,我希望能够以各种方式组合函数,例如:

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

如何创建这些功能?

4

4 回答 4

16

由于您没有给出如何观察结果的标准,因此a = b = c = id满足您的标准。但这当然不是你想要的。但是这个想法很重要:你希望你的函数具有什么样的行为并不重要,重要的是你将如何观察这种行为。

如果您在符号中允许一些自由度,则有一个最通用的模型,并且您可以通过使用代数数据类型来获得它:

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
...

等等。而不是说a b,你必须说A % B,但这是唯一的区别。您可以编写它们:

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

您可以通过部分应用将它们变成函数(%)

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

a但是,正如 ehird 所说,您无法对此进行比较。此模型与您指定的模型相同,只是看起来有些不同。

于 2012-03-16T23:12:36.807 回答
11

这是不可能的; 您无法将函数相互比较,因此无法检查您的参数是否为a,bc其他内容。

事实上,Haskell 不可能让您检查两个函数是否相同:因为 Haskell 是引用透明的,替换同一函数的两个不同实现应该没有效果。也就是说,只要您为每个输出提供相同的输入,函数的确切实现就无关紧要了,尽管证明\x -> x+x\x -> x*2是相同的函数很容易,但通常是不可判定的

a此外,如果要将自身作为参数,则没有可能的类型(当然,id id类型,但id可以将任何东西作为其第一个参数 - 这意味着它无法以您想要的方式检查它)。

如果你想用这个来实现一些东西(而不是仅仅出于好奇而玩弄它——当然这很好),那么你将不得不以其他方式去做。如果没有具体的细节,很难准确地说出这将是什么方式。

于 2012-03-16T22:59:57.057 回答
4

好吧,你可以这样做:

{-# LANGUAGE MagicHash #-}

import GHC.Prim
import Unsafe.Coerce

功能来自ehird的回答:

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

现在,让我们开始做生意。请注意,您需要强制参数和返回值,因为这些函数实际上不可能有任何类型,正如 ehird 指出的那样。

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

最后,一些测试:

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

呃……

于 2012-03-16T23:24:23.553 回答
0

如前所述,无法比较函数是否相等。如果您只是想要满足规范中的代数定律的函数,那么使它们都等于恒等函数会很好。

我希望您知道,如果您将与家庭作业相关的问题发布到 Stack Overflow,社区希望您能够识别它。

于 2012-03-17T01:30:43.447 回答