我想创建三个Haskell函数:a
,b
和c
。
每个函数都有一个参数。该论证是三个函数之一。
我希望函数a
具有此行为:
a
,则返回函数a
。b
。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
如何创建这些功能?
答案 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)
这是不可能的;你无法相互比较函数,因此无法检查你的论证是a
,b
,c
还是别的。
实际上,Haskell不可能让你检查两个函数是否相同:因为Haskell是引用透明的,所以替换相同函数的两个不同实现应该没有效果。也就是说,只要你为每个输出提供相同的输入,函数的确切实现就不重要了,虽然证明\x -> x+x
和\x -> x*2
是相同的函数很容易,但它是{ {3}}
此外,a
没有可能的类型,如果它将自己作为一个参数(当然,id id
类型,但id
可以采取任何作为它的第一个参数 - 这意味着它不能以你想要的方式检查它。)
如果你想用这个来实现某些目标(而不仅仅是出于好奇而玩它 - 当然这很好),那么你将不得不以其他方式做到这一点。如果没有具体的细节,很难准确地说出会是什么样的方式。
答案 2 :(得分:4)
嗯,你可以这样做:
{-# LANGUAGE MagicHash #-}
import GHC.Prim
import Unsafe.Coerce
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发布与家庭作业相关的问题,社区希望您将其识别为此类。