如何创建返回函数的Haskell函数?

时间:2012-03-16 22:55:34

标签: function haskell functional-programming higher-order-functions function-composition

我想创建三个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 个答案:

答案 0 :(得分: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所说。这个模型等同于你指定的模型,它看起来有点不同。

答案 1 :(得分:11)

这是不可能的;你无法相互比较函数,因此无法检查你的论证是abc还是别的。

实际上,Haskell不可能让你检查两个函数是否相同:因为Haskell是引用透明的,所以替换相同函数的两个不同实现应该没有效果。也就是说,只要你为每个输出提供相同的输入,函数的确切实现就不重要了,虽然证明\x -> x+x\x -> x*2是相同的函数很容易,但它是{ {3}}

此外,a没有可能的类型,如果它将自己作为一个参数(当然,id id类型,但id可以采取任何作为它的第一个参数 - 这意味着它不能以你想要的方式检查它。)

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

答案 2 :(得分:4)

嗯,你可以这样做:

{-# LANGUAGE MagicHash #-}

import GHC.Prim
import Unsafe.Coerce

此功能来自ehird的回答here

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

... EHH

答案 3 :(得分:0)

如上所述,无法比较函数的相等性。如果你只是想要在你的具体化中满足代数定律的函数,那么使它们都与标识函数相等就可以了。

我希望您知道,如果您向Stack Overflow发布与家庭作业相关的问题,社区希望您将其识别为此类。