ハスクでのゴルフのヒント


15

Huskは、PPCGユーザーのLeoZgarbによって作成された、まったく新しいゴルフ言語です。Jellyや05AB1Eなど、非常に簡潔であることが知られている言語の近くにとどまるか、さらには打ち負かすことさえあります。

ハスク特有のゴルフテクニックをいくつか挙げてみましょう。いつものように、回答ごとに1つのヒントを投稿してください。



1
@totallyhuman 最初のハスクの答えまだ新しいことではありません
-H.PWiz

回答:


10

述部からの戻り値を使用します

Huskでは、任意の正の整数が真実であるため、いくつかのプロパティの入力をテストする関数は通常、真実の場合に意味のある結果を返します。

例:

≠  Numbers: Absolute difference
   Chars:   Absolute difference of code points
   Lists:   First Index where the differ

Comparisons <, >, ≤, ≥:

For strict comparisons:
Numbers,Chars:  max 0 (the appropriate difference¹)
Lists: The first index where the comparison between the two lists is true

For non-strict comparisons:
Numbers,Chars: max 0 (the appropriate difference + 1)
Lists: Either the result of the strict comparison or, if they are equal,
       the length of the list + 1

ṗ  Index into the list of prime numbers

V  The index of the first element for which the condition is true

€  The first index of that element/substring in the list

£  Works like €

&  Given two arguments of the same type will return the second argument if false,
   otherwise will return the first argument

|  Given two arguments of the same type will return the second argument if true,
   otherwise will return the first argument

¦  Return the quotient if divisibility holds

Λ,E,Ë  Will all return length+1 in truthy cases

Char predicates:
□,±,√,D,½  will each return the codepoint of its argument on truthy cases

¹ 適切な差異とは、文字のコードポイントの差異を意味します。また、引数の順序も指します。すなわち<x yx-y


7

あふれるラインラベルを使用する

既にご存知かもしれ [₀-₉]+|[₀-₉]ませんが、現在の行とは異なる行を呼び出す構文の正規表現です。

このヒントは、特定の行で定義された関数を、以下の表の複数の関数の引数として、または以下の1つ以上の関数の引数として単独で呼び出す場合に特に役立ちます。

機能表:

+----------+----------+
|Index     |Function  |
+----------+----------+
|1         |´ (argdup)|
+----------+----------+
|2         |` (flip)  |
+----------+----------+
|3         |m (map)   |
+----------+----------+
|4         |z (zip)   |
+----------+----------+
|5         |S (hook)  |
+----------+----------+

コード内の行には、上から下へそれぞれの0から始まるインデックスでラベルが付けられます。もしN <M Mはラベルで、Nは、コードの行数で、ラベルはちょうどラインで定義された関数を表すMを。場合N≤M <N * 6、インデックスにおける上記テーブルから機能表す⌊M÷N⌋を行に定義された関数とM mod nを最初の引数として。N * 6≤Mの場合、インデックスエラーが発生します。


5

ラムダは新しい関数よりも短くすることができます

複数行のプログラムがある場合はおそらくご存知のよう₀…₉に、たとえば

f
g

関数を参照しますg。これで、入力を常に関数に適用するg(そしてそれを複数回使用する)場合; このようなもの:

f₁⁰[...]g₁⁰[...]
h

ラムダを導入する必要があります。ラムダを使用すると、追加の使用ごとに1バイトが節約されるためです。

λf⁰[...]g⁰[...])h

逆も同様です

自己参照型のラムダ(φχψ)の場合、入力を再帰関数に直接適用する特殊なケースがあります。これらの場合、新しいラムダを定義してを使用する代わりに、添え字を使用する方が良いでしょう


5

の使用 Γ

リストでのパターンマッチングまたはリストの分解Γと呼ばれる組み込みの主な用途は、リストを先頭と末尾に分割し、それらにバイナリ関数を適用することです。これはHaskellのパターンマッチングイディオムに対応します

f (x : xs) = <something>
f [] = <something else>

where <something>xxsおよびを含む式fです。の4つのオーバーロードがありΓ、それぞれが少し異なります。

list

最初のオーバーロードlistは、値aとバイナリ関数を取りますf。リストを受け取る新しい関数を返し、a空の場合は戻り、f空でない場合は先頭と末尾を呼び出します。たとえばΓ_1€、リストを-1取得し、空の場合は戻り、そうでない場合はテールの最初の要素の最初の出現のインデックスを返します。

listN

第二のオーバーロードはlistN、同様であるlistことを除いて、a省略され、戻り型のデフォルト値が代わりに使用されています。たとえば、Γ€Γ0€デフォルトの数値がであるため、と同等です0

デフォルト値は無関係であるか、正確に必要なものであるため、実際にlistNは、よりも頻繁に使用されlistます。一般的なパターンはΓ~αβγで、αβγ3つの関数があります。これはβ最初の要素とγテールに適用され、結果をと結合しますα。たとえば、この回答で使用されました。他のパターンには、最初の要素にのみΓo:α適用するαものと、最初の要素以外のすべての要素にΓ·:mα適用αするものがあります。後者はこの回答で使用されました

listF

3番目のオーバーロードはもう少し複雑です。のようにlist、値af関数gを受け取り、リストを受け取る新しい関数を返します。ただし、今回fは追加の関数引数を取ります。これはgそれ自体であり、任意の値(入力リストの末尾を含むが、これに限定されません)で呼び出すことができます。これは、リストにlistF一般的な再帰スキームを実装することを意味します。 /をlistF使用した明示的な再帰は、通常この回答のように同じ長さまたは短いため、あまり使用されません。listlistN

listNF

listNFあるlistFlistNにあるlistの入力は:a省略され、戻り値の型のデフォルト値が代わりに使用されます。まれに、この回答のように、右折りより短くなる場合があります

の再帰バージョンの例として、Γ関数Γλ·:o⁰↔はリストを最初、最後、2番目、最後から2番目、3番目、最後から3番目の順序でシャッフルします。 オンラインでお試しください! 関数fは明示的なlambda λ·:o⁰↔であり、その引数は関数全体です。何fんと、尾を逆であると再帰的にメイン関数を呼び出し、その後、o⁰、そして最後に頭のバックタック·:。もちろん、Γ·:o₀↔バイトは短くなりますが、行にこの関数以外のものが含まれている場合は機能しません。


3

コンビネータは高次関数に適用できます

整数Xのリストがあり、length(X)より大きいXの要素の総数をカウントするとします。述部を満たす要素のカウントは高次関数で行われますが、ここでは述部(length(X)より大きい)はXに依存します。解決策は、コンビネータ適用することであるとし、機能リストは数よりも短くなっているかどうかのチェックを。関数では、リストXはに渡され、部分的に適用された関数はに渡され、Xは2番目の引数として渡されます。##o>LṠ#o>Lo>L##

一般に、αが高階関数である場合β、バイナリ関数とγ単項関数ṠαβはHaskell擬似コードと同等です。

\x -> α (\y -> β x y) x

§αβγ に等しい

\x -> α (\y -> β x y) (γ x)

~αβγ同等です

\x y -> α (\z -> β x z) (γ y)

タイプが一致する限り。

別の具体例として、§►δṁ≠Pリストの順列見つけXの値が対応する差分絶対値和を最大Xをδṁ≠絶対差を使用して2つのリストをジッパーとの和をとります)。


3

ハスクのデフォルト値

ハスクは、たとえばlast空のリストの要素を取得しようとしたときに問題が発生するHaskellほど厳密ではありません。これを実現するために、定義済みの値を使用します。デフォルト値、最大値と最小値のリストは次のとおりです。

.------------------------------------.---------------.----------.-------.
|   Type (X and Y are placeholders)  | default (def) |    max   |  min  |
|------------------------------------|---------------|----------|-------|
|       Character (C)                |      ' '      | \1114111 | \NUL  |
|       Numbers   (N)                |       0       |   Inf    | -Inf  |
|       List of X (LX)               |      []       |  ∞ max   |   []  | *
|       Function :: X -> Y           | const (def Y) |   n/a    |  n/a  |
'------------------------------------'---------------'----------'-------'

*ここで、∞は対応する最大値の無限リストを表す必要があります(例については以下を参照)

注:タプル(X、Y)の場合、各コンポーネントの値を個別に使用します。


それらが使用されるとき

最大値と最小値は▲▼空のリストでのみ使用されますが(たとえばhusk -u "▼" "[]:LLN"、無限のリストを返しInfます)、デフォルト値はいくつかの場所で使用されます:

  • 自分で値を指定せずに空のリストを折り畳む(Fおよび
  • デフォルト値の前に(を付けてΘ
  • 読み取り(r)が失敗したとき
  • 最初/最後の要素の取得(←→)または1つへのインデックス付け(!
  • Γ空のリストでのパターンマッチング()
  • 使用または空のリストに
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.