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

Function 如何创建返回函数的Haskell函数?,function,haskell,functional-programming,higher-order-functions,function-composition,Function,Haskell,Functional Programming,Higher Order Functions,Function Composition,我想创建三个Haskell函数:a、b和c 每个函数都有一个参数。参数是三个函数之一 我希望函数a具有以下行为: 如果参数是functiona,则返回functiona 如果参数是函数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 创建后,我希望能够以各种方式组合函数,例

我想创建三个Haskell函数:
a
b
c

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

我希望函数
a
具有以下行为:

  • 如果参数是function
    a
    ,则返回function
    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

如何创建这些函数?

这是不可能的;您无法相互比较函数,因此无法检查参数是
a
b
c
还是其他

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

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


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

这是不可能的;您无法相互比较函数,因此无法检查参数是
a
b
c
还是其他

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

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


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

既然您没有给出如何观察结果的标准,那么
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
...
等等。不要说
ab
,你必须说
a%b
,但这是唯一的区别。您可以编写它们:

  A % (C % B)
= A % B
= B
您可以通过部分应用
(%)
,将它们转换为函数:


但是你不能像ehird所说的那样,将这个
a
进行比较。此模型与您指定的模型相同,只是看起来有点不同。

由于您没有给出如何观察结果的标准,因此
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
...
等等。不要说
ab
,你必须说
a%b
,但这是唯一的区别。您可以编写它们:

  A % (C % B)
= A % B
= B
您可以通过部分应用
(%)
,将它们转换为函数:


但是你不能像ehird所说的那样,将这个
a
进行比较。此型号与您指定的型号相同,只是看起来有点不同。

您可以这样做:

{-# LANGUAGE MagicHash #-}

import GHC.Prim
import Unsafe.Coerce
此函数来自的答案:

现在,让我们谈正事吧。请注意,正如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

嗯…

你可以这样做:

{-# LANGUAGE MagicHash #-}

import GHC.Prim
import Unsafe.Coerce
此函数来自的答案:

现在,让我们谈正事吧。请注意,正如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

呃…

如前所述,函数不能进行相等性比较。如果您只是希望函数满足您的规范中的代数定律,那么让它们都等于恒等式函数就很好了


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

如前所述,函数不能进行相等性比较。如果你只是想要满足你规范中代数定律的函数,m