まず、コードをフォーマットします。
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun t = (\b -> if b == (pred (fst t))
then Nothing
else Just (b, pred b)) (snd t)
次に、Hoogleunfoldr
を使用するタイプを再確認します。
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
次に、型シグネチャを に追加しfun
て、GHC が問題を教えてくれるようにします。のタイプによると、 は次のタイプをunfoldr
持つfun
必要があります。
b ~ Char
a ~ Char
fun :: Char -> Maybe (Char, Char)
あなたはunfoldr
元の例にいるのでsnd t
。
私は通常、小さな断片を検証するのが好きなので、 の定義を削除してfoo
、型シグネチャのみを使用できます。
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun t
fun:: Char -> Maybe (Char, Char)
fun b = error ""
t
GHC は、 type を持っているが type(Char, Char)
をfun
期待していると文句を言いChar
ます。元の例のunfoldr fun t
代わりに呼び出しました。unfoldr fun (snd t)
そのビットを から に移動しfun
ますrevRange
。
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr fun (snd t)
fun:: Char -> Maybe (Char, Char)
fun b = error ""
次に、fun
再度の定義を追加します。ラムダを削除しb
て、通常の引数として次のように設定できますfun
。
fun:: Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
すぐに、別の明らかな問題が発生します。2 つのfun
引数を取りますが、署名は 1 つだけを取るべきだと言っています!
は元のラムダの定数であるため、 を部分的に適用することでt
この問題を解決できるため、最終的な答えは次のようになります。fun
revRange
revRange :: (Char,Char) -> [Char]
revRange t = unfoldr (fun t) (snd t)
fun:: (Char, Char) -> Char -> Maybe (Char, Char)
fun t b = if b == (pred (fst t))
then Nothing
else Just (b, pred b)
あなたのコメントに対処するために、あなたは書きたいです
revRange :: (Char,Char) -> [Char]
revRange = unfoldr fun2
上記と同じアプローチを使用して、 の署名でとunfoldr
が必要です。そのため、タイプが必要ですb ~ (Char,Char)
a ~ Char
fun2
fun2 :: ((Char,Char) -> Maybe (Char, (Char, Char)))
の定義はfun2
練習問題として残しておきます。ヒントとして、ペアの最初の部分が定数であり、 が成り立つという規則を採用することをお勧めしますfst t
。