1

ab、 の3 つの Haskell 関数を作成したいと思いますc

各関数には 1 つの引数があります。引数は、3 つの関数の 1 つです。

a関数にこの動作をさせたい:

  • 引数が function の場合、 functionaを返しますa
  • 引数が関数 b の場合は、 function を返しますb
  • 引数が関数 c の場合、関数を返しますa

関数に必要な動作の要約を次に示しますa

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

そして、他の2つの機能に私が望む動作は次のとおりです。

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

不可能だよ; 関数同士を比較することはできないため、引数がabcまたはその他のものであるかどうかを確認する方法はありません。

実際、Haskell で 2 つの関数が同じかどうかをチェックすることは不可能です。Haskell は参照透過であるため、同じ関数の 2 つの異なる実装を置き換えても効果はありません。つまり、すべての出力に同じ入力を与える限り、関数の正確な実装は重要ではなく、 と が同じ関数であることを証明する\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の回答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

ええと...

于 2012-03-16T23:24:23.553 に答える
0

前述のように、関数が等しいかどうかを比較することはできません。仕様の代数法則を満たす関数が必要な場合は、それらをすべて恒等関数と等しくすることでうまくいきます。

宿題に関連する質問をStackOverflowに投稿すると、コミュニティはそれをそのように特定することを期待していることをご承知おきください。

于 2012-03-17T01:30:43.447 に答える