2

最短のコードを優先するreglementationがあるため、非常に短いコードを作成しようとしました。リストを同じ順序で昇順リストと降順リストの新しいリストに変換する関数を作成する必要があります。たとえば、次のようになります。[1,6,2,1,7,3,2,8,4]、になります[[1,6],[2,1],[7],[3,2],[8],[4]]

だから私は次のことをしようとしました:

func :: Ord a => [a] -> [[a]]
func xs = f1 d [a]
f1 [] ys = [c]
f1 xs ys    | a >= b = d `f1` a:ys
            | otherwise = c: d `f2` [a]
f2 [] ys = [c]
f2 xs ys    | a < b = d `f2` a:ys
            | otherwise = c : d `f1` [a]
    where   a = head xs
            b = head ys
            c = reverse ys
            d = tail xs

しかし、私は得る

parse error on input '=' 

line "b = head ys"

whereブロックで複数の関数を定義することは可能だと思いましたか?

他のくぼみは、多くのようなエラーを作成しました

not in scope 'a'
not in scope 'b'
not in scope 'c'
not in scope 'd'

また

parse error on input 'b'

いくつかのトークンを保存する/コードを短くするために、そのようにする必要があります。

4

3 に答える 3

2

インデントよりも根本的な問題があります。whereブロックは単一の関数の場合にローカルです。ブロックを使用して、一連の関数全体にバインディングwhere(、、、、など)を提供aしよbうとしています。これは機能しません。cd

明確にするために、この正しくインデントされたコードは機能しません。

foo :: Int -> Int
foo 0 = a
foo 1 = b
  where a = 2
        b = 3

のようなエラーが発生しますNot in scope: `a'。これは、ケース全体にwhereのみ拡張されるためです。foo 1それはケースにさえ行きませんfoo 0、ましてや他の機能はありません。

一方、あなたのコードは、whereブロックがすべての機能で機能することを期待しているようです。さまざまな関数で表示できるバインディングを使用するには、それらを関数自体と同じレベルのスコープに配置する必要があります。

また、Haskellのインデントは少し厄介です。あなたは本当にタブを避けるべきです。Haskellを正しく理解するエディターがいることも本当に役に立ちます。ここではEmacsが非常に優れていることがわかりました。EmacsでのHaskellのインデントについて心配する必要はありません。

Emacsには少し学習曲線があるかもしれませんが(チュートリアルを行う必要があります)、それだけの価値があると思います。Haskellモードもインストールする必要があります。Emacsの最新バージョンを入手した場合は、パッケージマネージャーを使用してこれを行うことができるはずです。

于 2012-11-10T18:52:56.637 に答える
2

コンパイラには次のように表示されます。

func :: Ord a => [a] -> [[a]]
func xs = f1 d [a]
f1 [] ys = [c]
f1 xs ys    | a >= b = d `f1` a:ys
                | otherwise = c: d `f2` [a]
f2 [] ys = [c]
f2 xs ys    | a < b = d `f2` a:ys
                | otherwise = c : d `f1` [a]
            where    a = head xs
                        b = head ys
                        c = reverse ys
                        d = tail xs

したがって、コンパイラの場合、最初の行の後のwhere句の行は、その行の継続のように見えます。もちろん=、1行にセミコロンを挿入しないと複数の行を含めることはできません。

タブとスペースを混在させないでください(実際には、タブを使用しないでください)。また、タブを使用する場合は、タブを8つのスペースとして解釈するようにエディターを構成します。

また、このwhere句は最後の方程式のみを対象としているためa, b, c, d、の最初の4つの方程式には範囲がありませんfunc

于 2012-11-10T18:53:18.073 に答える
0

エラー メッセージは、タブとスペースが混在しているためです。スペースのみを使用することをお勧めします。

さて、あなたが書いているなら

a = head xs
b = head ys
c = reverse ys
d = tail xs

それから

xs = (a:ds)
ys = (b:es)

パターン マッチングを使用して関数を書き直してみましょう。

func :: Ord a => [a] -> [[a]]
func [] = []
func (a:ds) = f1 ds [a]
f1 [] ys = [reverse ys]
f1 (a:ds) (b:es) | a >= b = ds `f1` (a:b:es)
                 | otherwise = reverse (b:es): ds `f2` [a]
f2 [] ys = [reverse ys]
f2 (a:ds) (b:es) | a < b = ds `f2` (a:b:es)
                 | otherwise = reverse (b:es) : ds `f1` [a]

これが長くなることは承知していますが、ご了承ください。f1は実際には と同じですf2が、比較が変更されています。no比較を否定する関数を取得しましょう(no (>=)) x y = not (x >= y)

no cmp x y = not (cmp x y)

実際、これは次のように書くことができます。

no = ((not.).)
r = reverse

func' (a:ds) = f (>=) ds [a]
f :: Ord a => (a -> a -> Bool) -> [a] -> [a] -> [[a]]
f _ [] ys = [r ys]
f cp (a:ds) ys@(b:es) | cp a b = f cp ds (a:ys)
                      | True = r ys : f (no cp) ds [a]

これで短くなりました。

于 2012-11-10T21:38:10.553 に答える