3

「Person」という名前のクラスがあります

Person :: String -> String -> Int -> Gender -> Person

目標: Personのより一般的なバージョンを作成するには、GenderをFemaleに割り当ててfemalePersonを作成します。

機能: 最初のN個の要素のバインドが機能します:

let personsWithNameAlice = Person "Alice"
let personsWithNameAliceMcGee = Person "Alice" "McGee"

動作しないもの:

let femalePerson = Person {gender = Female}

質問:

  • これを行うにはどうすればよいですか?
  • n!= 0の関数のn番目の要素に値をバインドするにはどうすればよいですか?

数学ではf(x、y、z)= g(x、y、z、5)、C++ではstd:: bind2nd(f、8)と書くことができるので、Haskellではできないはずです。 ?

4

2 に答える 2

13

セマンティックエディタコンビネータを使用します。たとえば、次の関数があるとします。

foo :: Int -> String -> Bool -> Char -> Float
foo = undefined

すべての異なる型を含むように例を変更したので、型チェックにより、定義が正しいことを確認できます。次の4種類の特殊化が必要です。それぞれ、1つの引数を入力した結果です。

foo0 ::        String -> Bool -> Char -> Float  -- 3
foo1 :: Int ->           Bool -> Char -> Float  -- "hey"
foo2 :: Int -> String ->         Char -> Float  -- True
foo3 :: Int -> String -> Bool ->         Float  -- 'x'

最初のものは簡単で、まっすぐな部分適用です:

foo0 = foo 3

ただし、(他の人との一貫性を保つために)奇妙な方法で記述しましょう。

foo0 = ($ 3) foo

resultその他の場合は、compositionの同義語であるを使用します。

result :: (b -> b') -> ((a -> b) -> (a -> b'))
result = (.)

のアプリケーションはresult、特定の関数を別の関数の「結果」に向けます(したがって、firstおよびsecondからの関数に直接類似していますControl.Arrow)。次に、繰り返されるアプリケーションは、必要に応じて、連続するカレーされた引数をスキップして、複数の結果の内部を目指します。

foo1 = result ($ "hey") foo
foo2 = (result.result) ($ True) foo
foo3 = (result.result.result) ($ 'x') foo

resultn番目のスペシャライゼーションはそれ自体でn回合成されたものを使用することに注意してください。

于 2012-07-25T17:39:14.877 に答える
7

与えられたラムダ式でそれを行うことができます

Person :: String -> String -> Int -> Gender -> Person

あなたが定義する

femalePerson = \fn ln a -> Person fn ln a Female

または、バインディングに引数を使用します。

femalePerson fn ln a = Person fn ln a Female

2番目のパラメーターを具体的にバインドする場合flipは、必要な関数です

third = flip (/) 3

引数を任意の位置にバインドするために使用できますflipが、それはすぐに面倒で読みにくくなります。

femalePerson = curry . curry $ flip (uncurry (uncurry Person)) Female
于 2012-07-25T12:23:46.430 に答える