0

これは私がやりたいことです:

INPUT: [1,2,3,-1,-2,-3]
OUTPUT:[1,1,1,-1,-1,-1]

私はこれを試しました:

signNum (x:n) = map(if x>0 
            then 1 
            else -1)n

ロジックのどこで間違いを犯したか教えてもらえますか?

4

4 に答える 4

2

最初の問題はmap、関数を期待することです。ifしたがって、ステートメントをラムダでラップする必要があります。ただし、これでも希望どおりにはなりません。リストを先頭と末尾に分割する代わりに、関数をリスト全体にマップする必要があります。

map関数を取り、それを各要素に適用するだけであることを忘れないでください。1各要素を または のいずれかに変換したいので-1、リストに適切な関数をマップするだけです。

したがって、最終的には次のようになります。

sigNum ls = map (\ x -> if x > 0 then 1 else - 1) ls
于 2012-10-14T17:02:44.023 に答える
1

この場合、関数をより小さな部分に分割する方がおそらく簡単です。

最も低いレベルでは、1 つのsignum数値の を計算できます。つまり、次のようになります。

signum :: (Num a, Ord a) => a -> a
signum x = if x > 0 then 1 else -1

これを取得したら、他の関数の場合と同様に、数値のリストで使用できます。

signNum ls = map signum ls

(ps とはどういうsignum 0意味ですか?現在の定義にはsignum 0 = -1.

このケースを含めるために関数を拡張する必要がある場合は、ガードを使用することをお勧めします。

signum x | x < 0 = -1
         | x == 0 = 0
         | otherwise = 1

またはケースステートメント:

signum x = case compare x 0 of 
             LT -> -1
             EQ -> 0
             GT -> 1

)

于 2012-10-14T17:13:04.677 に答える
1

あなたのコメントは、あなたがこれを理解したいと思っていることを示唆しています。

了解の使い方

あなたが理解してこれをしたいのなら、あなたはすることができます

signNum ls = [ if x>0 then 1 else -1| x <- ls ]

理解を使わない方法

...しかし、右辺に条件を置くことはできません

brokenSignNum ls = [ 1| x <- ls, x > 0 ]

条件を右側に置くと、条件を満たさないものはすべて削除されるため、マイナスはすべて無視されます。これにより、要素が置き換えられるのではなく、リストが短くなります。やってみよう

brokenSignNum2 ls = [ 1| x <- ls, x > 0 ] ++ [ -1| x <- ls, x <= 0 ]

これは元のリストと同じ長さですが、すべてのポジティブが先頭にあります。

要約: この条件式は左側に配置する必要があります。これは、置換が発生する唯一の場所であるためです。右側では、削除が行われます。

ゼロはマイナスですか?

if ステートメントは 0 を負としてカウントすることに注意してください。本当にそれが欲しいですか?おそらく、数値の符号を個別に定義したほうがよいでしょう。

sign x | x == 0 = 0   -- if x is zero, use zero
       | x > 0 =  1   -- use 1 for positives
       | x < 0 = -1   -- use -1 for negatives

workingSignNum1 ls = [sign x | x <- ls]

しかしsign、(ほぼ) function と同じなsignumので、それを使用することもできます

workingSignNum2 ls = [signum x | x <- ls]

整理整頓

これで、基本的に「リスト全体xを置き換える」という意味の構文がたくさんあります。私たちはそのようなことをよくするので、それを行う関数を書くことができます:sign xls

replaceUsing :: (a -> b) -> [a] -> [b]
replaceUsing f xs = [f x | x <- xs]

しかし、それを行う機能がすでにあります!と呼ばれていmapます。したがって、リストで map を使用できます。

quiteSlickSignNum :: Num a => [a] -> [a]
quiteSlickSignNum ls = map signum ls

またはさらに滑らか:

slickSignNum :: Num a => [a] -> [a]
slickSignNum = map signum

それが私がそれを定義した方法です。

なぜ とほとんど同じだと言っsignたのですか?signum

signは数値を受け取り、10、またはを返します-1が、 の型は1何ですか?
さて、1型を持っているNum a => aので、任意の数値型で使用できます。これは sign、任意の型の数値を取り、任意の型の数値を返すことを意味するため、その型は

sign :: (Num a,Num b) => a -> b

そのため、私のバージョンのsignは別のタイプを提供できます。試してみると、 ではなくが3 * sign 4.5得られるので、整数を取得できますが、 を取得すると が得られるため、10 進数型も取得できます。対照的に、33.03.14 * sign 7.43.14

signum :: Num a => a -> a

そのため、指定した型のみを返すことができます -3 * signum 4.5を与えます3.0

于 2012-10-15T06:15:19.527 に答える
0

エラーメッセージ "no instance for Num" は、新しい Haskeller が解読するのが最も難しいものの 1 つです。まず、記述しようとしている関数の完全にポリモーフィックな型シグネチャを次に示します (同じエラーを取得するために、これをソース ファイルに追加しました)。

signNum :: (Ord a, Num a) => [a] -> [a]

エラーを見つける

現在、コンパイルエラーメッセージは次のように表示されています。

prog.hs:3:17 のリテラル `1' から生じるコンテキスト (Ord a, Num a) から (Num (a -> a)) を推測できませんでした。

エラー メッセージが問題の場所を示していることに注意してください。「リテラル 1」 atfile_name.hs:line_number:column_numberが問題であると書かれています。

signNum (x:n) = map(if x>0 
            then 1 -- <-- here's the problem! (according to that message)
            else -1)n

エラーを理解する

現在、エラー メッセージはいくつかの可能な修正も示唆していますが、「no instance for Num」に遭遇するたびに、提案された「可能な修正」はほとんどの場合間違っているため、無視してください。Num(GHC が、このような に関連するエラー メッセージをより適切に提供してくれることを願っています)。

エラー メッセージの内容を思い出してください。

推論できませんでした (Num (a -> a)) ... リテラル `1' から生じる ...

1これが意味することは、コンテキストが type の何かを期待する場所にリテラルを配置することです
a -> a1は明らかに関数ではないため、コンテキストが間違っているか、数字の 1 が間違っています。

では、リテラル 1 のコンテキストは何ですか?

エラーを見つける(正確に)

(if x > 0
  then <<hole>>
  else -1)

Haskell の if ステートメントは値を生成します。if ステートメントの分岐は同じ型でなければならず、if ステートメントの型は分岐の型によって決まります。

ここで、もう一方のブランチの値-1は数値です。したがって<<hole>>、 が同じ型、つまり数値を持つことが期待されます。これは明らかに問題ではありません (1は数値であるため) ので、その式のコンテキストを見てみましょう。

map <<hole>> n

このmap関数は、最初の引数として関数を想定しています。<<hole>>ただし、が数値を生成することはわかっています。ユーレカ!ここに不一致がmapあります。関数が必要な場所に数値を指定しています。

エラーの修正

問題が何でどこにあるかが正確にわかったので、明白な解決策はmap、数値ではなく関数を与えることです。詳細については、他のさまざまな回答を参照してください。

于 2012-10-15T16:01:12.907 に答える