1

Haskellの3つの関数、すなわちab、およびcを作成したいと思います。関数を返すHaskell関数を作成するにはどうすればよいですか?

各機能には1つの引数があります。引数は3つの関数のうちの1つです。引数は、関数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 

これらの機能を作成するにはどうすればよいですか?

+2

あなたはそれらを比較できるようにいくつかのデータで関数にタグを付けなければなりません。つまり、プレーンな関数を使うことはできません。いくつかの比較可能な値を持つデータ型にそれらを配置する必要があります。 –

+1

あなたはこれまで何をしていますか?あなたは関数の署名を持っていますか? –

+3

これを達成することで何をしようとしていますか? –

答えて

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 %) 

しかしehirdが言うように、あなたは、このaを比較することはできません。このモデルはあなたが指定したモデルと同等ですが、ちょっと違って見えます。

+4

あなたは 'a'だけを比較することができます:'インスタンスEq(F - > F)f == g =すべて(\ x - > fx == gx)[A、B、C] ' –

+0

@SjoerdVisscher、oh 、それは有限であるから、右。私はいつもそのことを忘れています。 – luqui

11

これは不可能です。関数同士を比較することはできないので、引数がabcなどであるかどうかをチェックする方法はありません。

実際には、Haskellは2つの関数が同じかどうかをチェックさせることはできません。つまり、Haskellは参照を透過的に扱うので、同じ関数の2つの異なる実装を置き換えることは効果がありません。つまり、すべての出力に対して同じ入力を与える限り、関数の正確な実装は重要ではありません。\x -> x+x\x -> x*2が同じ関数であることを証明しても簡単ですが、undecidable in generalです。

さらに、それは引数(必ず、id idタイプとしての地位を取るかどうaを持つことができることは可能なタイプがありませんが、idはその最初の引数としてを取ることができます - それは、それを調べることができないことを意味しますあなたがしたい方法)。

これで何かを達成しようとしている場合(好奇心から遊んでいるのではなく、もちろん)、何か他の方法でやる必要があります。具体的な詳細がなければ、どのようになるかを正確に言うのは難しいです。

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 

をそれでは、ビジネスに取得してみましょう。あなたが指摘したように、これらの関数が実際に持つことができる型がないので、引数と戻り値を強制する必要があることに注意してください。

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 

えっ...

+0

あなたは19の非危険な '危険な'でそれをすることができますが、あなたは20でそれをすることができますか? – luqui

+0

@luqui:第20回 'unsafeCoerce'が隠れています(http://hpaste.org/65425) – danr

+3

@luqui確かに! 'reallyUnsafe'は2倍です。 –

0

は、機能が等しいかどうかを比較することはできません。あなたの特異性の代数的法則を満たす関数を単に必要とするならば、それらを全て同一関数と等しくすることはうまくいくでしょう。

宿題関連の質問をStack Overflowに投稿すると、コミュニティはあなたにそれを識別することを期待しています。

+2

非常に残酷な、非常に無知な、または非常に不明な先生だけがこれを宿題の問題として割り当てるでしょう。 –

+2

@ダンバートン:同意。しかし、それが宿題でなければ、地球上のどこから来るのでしょうか? –

関連する問題