0

remdpsリスト内の最も近い重複を削除する、関数の実装を作成しようとしています。例:"aaabbbsscaa"になったはず"absca"です。私は使用する必要がありますfoldl。これが私の試みです:

helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if tail newlist /= ele then newlist:ele
    else newlist

remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list

main = putStrLn (show (remdps "aabssscdddeaffff"))

そしてエラー:

4.hs:4:41:
    Could not deduce (a ~ [a])
    from the context (Eq a)
      bound by the type signature for helper :: Eq a => [a] -> a -> [a]
      at 4.hs:2:11-33
      `a' is a rigid type variable bound by
          the type signature for helper :: Eq a => [a] -> a -> [a]
          at 4.hs:2:11
    In the second argument of `(/=)', namely `ele'
    In the expression: tail newlist /= ele
    In the expression:
      if tail newlist /= ele then newlist : ele else newlist

4.hs:4:50:
    Could not deduce (a ~ [a])
    from the context (Eq a)
      bound by the type signature for helper :: Eq a => [a] -> a -> [a]
      at 4.hs:2:11-33
      `a' is a rigid type variable bound by
          the type signature for helper :: Eq a => [a] -> a -> [a]
          at 4.hs:2:11
    In the first argument of `(:)', namely `newlist'
    In the expression: newlist : ele
    In the expression:
      if tail newlist /= ele then newlist : ele else newlist

4.hs:4:58:
    Could not deduce (a ~ [a])
    from the context (Eq a)
      bound by the type signature for helper :: Eq a => [a] -> a -> [a]
      at 4.hs:2:11-33
      `a' is a rigid type variable bound by
          the type signature for helper :: Eq a => [a] -> a -> [a]
          at 4.hs:2:11
    In the second argument of `(:)', namely `ele'
    In the expression: newlist : ele
    In the expression:
      if tail newlist /= ele then newlist : ele else newlist
fish: Unknown command './4'
ghc 4.hs; and ./4

質問は常に同じです:)。どうしたの?

//編集

OK、私は実用的なコードを持っています。reverseandを使用する++ため、非常に醜いです:)。

helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if head (reverse newlist) /= ele then newlist ++ [ele]
    else newlist

remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list

main = putStrLn (show (remdps "aabssscdddeaffff"))
4

4 に答える 4

2

おそらくあなたがやろうとしているのはこれです:

helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if last newlist /= ele then newlist ++ [ele]
    else newlist

変更:

  • :1 つの方法でのみ機能します。左側がリストの先頭 ( type a)、右側が末尾 ( type [a]) です。「短所」と呼ばれることもあります。あなたがしたいことは「snoc」と呼ばれます:その右側はリストの最後の要素( type a)で、左側は最初の部分( type [a])です。

    "snoc" は Prelude には存在しないので、代わりに別の方法で書きます: newlist ++ [ele]. (これを と比較してくださいx : xs == [x] ++ xs。)

  • tail newlist == eleになりlast newlist == eleます。tailは先頭のないリストを取得しますが、 の最後の要素を比較したいと考えていますnewlist。そのために、last. (ちなみに、リストの最初の部分を取得するには、 を使用できますinit。)

if ステートメントのブランチも交換したことに注意してくださいaaa。答えはそのままです。-編集-あなたが今それを更新したようです;)


また、これは非常に遅いアプローチであることに注意してください。Prelude リストは "cons last"と. 代わりに "cons" を使用するように関数を書き直してみてください。ヒント:ある時点で必要になります。remdpsheadreverse

さらに、この関数は、動作方法が原因で、無限リストで使用すると機能しませんfoldl。この関数を書き直してfoldr代わりに使用するのは興味深い演習になるかもしれません。

于 2013-01-09T01:16:55.413 に答える
1

ヘルパーの型注釈は、 ele型が a
であることを示し ています。次のテスト(tail(newlist) == ele)を実行しますが、型が [a]の場合は tail

タイプが異なる場合、2 つの値を比較することはできません。

エラーはこれだけではありません。

于 2013-01-09T01:05:04.880 に答える
1

Data.Listのドキュメントをご覧になることをお勧めします。具体的にtailは、タイプが であることがわかります。その[a] -> [a]ため、考えられるようにリストの最後の要素を返さないことは明らかです。

リスト (最後のリスト) から単一の要素を取得しようとしている場合は、 type を持つものが必要です[a] -> a。Haskell の威力は、この情報だけで適切な関数を見つけるのにほぼ十分であるという事実に由来します。

フーグルするだけ

PS補足として-Tinctoriusの回答で述べたように、このアプローチは非常に遅いです

于 2013-01-09T01:19:47.420 に答える
1

私の2番目のコメントを拡張すると、これはあなたの質問に答えていませんが、私はfoldlこれを行うことはほとんどありません. 私のScheme時代に戻って、私はこのペットkfoldr関数でそれを解決しました.

-- |  A special fold that gives you both left and right context at each right
-- fold step.  See the example below.
kfoldr :: (l -> a -> l) -> l -> (l -> a -> r -> r) -> (l -> r) -> [a] -> r
kfoldr advance left combine seedRight [] = seedRight left
kfoldr advance left combine seedRight (x:xs) = combine left x (subfold xs)
where subfold = let newLeft = advance left x 
                in newLeft `seq` kfoldr advance newLeft combine seedRight


removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = kfoldr advance Nothing step (const [])
    where 
      -- advance is the left context generator, which in this case just 
      -- produces the previous element at each position.
      advance _ x = Just x
      -- step's three arguments in this case are:
      --   (a) the element to the left of current
      --   (b) the current element
      --   (c) the solution for the rest of the list
      step Nothing x xs = x:xs
      step (Just x') x xs
           | x == x' = xs
           | otherwise = x:xs

Haskell のData.ListライブラリにはmapAccumLとがあり、mapAccumRどちらも似ていますが、折りたたみではなくマップされます。また、密接に関連するscanlandもありscanr、おそらく実装に使用できますkfoldr(ただし、試してみませんでした)。

于 2013-01-09T01:24:54.730 に答える