0

compress xs@(_:_:_) = (ifte <$> ((==) <$> head <*> head.tail) <$> ((compress.).(:) <$> head <*> tail.tail) <*> ((:) <$> head <*> compress.tail) ) xs

タイプエラーが発生しますが、理由がわかりません。と同等である必要があります

compress xs@(_:_:_) = (ifte (((==) <$> head <*> head.tail) xs) (((compress.).(:) <$> head <*> tail.tail) xs) (((:) <$> head <*> compress.tail) xs))

、そうではありません。

注:ifte = (\ x y z -> if x then y else z)<$>および<*>はからControl.Applicativeです。

編集:エラーは次のとおりです。

Couldn't match expected type `[a]' with actual type `[a] -> [a]'
    In the expression:
        (ifte <$> ((==) <$> head <*> head . tail)
     <$>
       ((compress .) . (:) <$> head <*> tail . tail)
   <*>
     ((:) <$> head <*> compress . tail))
      $ xs
    In an equation for `compress':
        compress xs@(_ : _ : _)
          = (ifte <$> ((==) <$> head <*> head . tail)
         <$>
           ((compress .) . (:) <$> head <*> tail . tail)
       <*>
         ((:) <$> head <*> compress . tail))
          $ xs

私は、99のHaskell問題の問題8に対する無意味な解決策を書き込もうとして、この問題に遭遇しました。私は自分が書いた意味のある解決策を修正することによってそれをやろうとしていました。

compress::Eq a => [a]->[a]
compress [] = []
compress (x:[]) = (x:[])
compress (x:y:xs) = ifte ((==) x y) (compress (x:xs)) (x:(compress (y:xs)))
4

3 に答える 3

6

まず、インデントします。次に、いくつかの変数の使用を検討してください。

より賢明なフォーマットでも、それが

compress =
  ifte <$> ((==) <$> head <*> head.tail)
       <$> ((compress.).(:) <$> head <*> tail.tail)
       <*> ((:) <$> head <*> compress.tail)

いつあるべきか

compress =
  ifte <$> ((==) <$> head <*> head.tail)
       <*> ((compress.).(:) <$> head <*> tail.tail)
       <*> ((:) <$> head <*> compress.tail)

第三に、あなたが不可解でなければならないとしても、どうですか

compress (x:r@(y:_)) = ifte (x==y) id (x:) $ compress r

または、ポイントフリー

compress = map fst . filter (uncurry (/=)) . (zip <$> id <*> tail)
于 2011-10-22T21:13:46.207 に答える
5

もう少し読みやすい方法で書かれたコードは次のとおりです

{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Applicative

u = ((==) <$> head <*> head.tail)
v = ((compress.).(:) <$> head <*> tail.tail)
w = ((:) <$> head <*> compress.tail)

ifte = (\ x y z -> if x then y else z) 

--compress xs@(_:_:_) = (ifte <$> u <$> v <*> w) xs
compress xs@(_:_:_) = (ifte (u xs) (v xs) (w xs))

間違いがわかると思います - 正しいバージョンは

--compress xs@(_:_:_) = (ifte <$> u <*> v <*> w) xs
于 2011-10-22T20:58:10.703 に答える
2

これはすでに述べたことと非常によく似ていますが、少しの間私を甘やかして、型の価値について説教させてください.

import Control.Applicative

ifte :: Bool -> a -> a -> a
ifte b t f = if b then t else f

compress :: Eq a => [a] -> [a]
-- compress = ifte <$> cond <$> t <*> f
-- We will leave compress undefined so we can load this into ghci.
-- After some trial and error it is clear that this is the part
-- that doesn't type check
compress = undefined

cond :: Eq a => [a] -> Bool
cond = (==) <$> head <*> head . tail

t :: Eq a => [a] -> [a]
t = (compress .) . (:) <$> head <*> tail . tail

f :: Eq a => [a] -> [a]
f = (:) <$> head <*> compress . tail

ここで私はそれを分割しました。Brandon が述べたように、この時点でエラーは<$>where <*>should be の使用にあることがわかります。applicative スタイルを学習し続けるにつれて、その概念に慣れるでしょう。通常、式には単一の<$>後に続く任意の # があり<*>ます。

f <$> a <*> b <*> c <*> d <*> ...

ただし、その洞察を無視して、ここでは各部分式に型と TLD を一時的に指定しました。これにより、ファイルを ghci にロードして、少し遊んでみることができます。

ghci> :t ifte <$> cond <$> t <*> f
... Eq a => [a] -> [a] -> [a]

なんだ???型音ですか???エラーになるはずだったのですが、どうやらこの表現はOKのようです。またはそれは?この型シグネチャは、必要なものと一致しないことにcompress注意してください。

ghci> :t compress
... Eq a => [a] -> [a]

副次式は、期待する型シグネチャと一致します。これは、コンパイラが吐き気を催していないことからも明らかです。ですから、問題は明らかにそれらの組み合わせ方にあります。では、ここで組み合わせたい部品は何ですか? Eq 制約を無視します。

ifte :: Bool -> [a] -> [a] -> [a]
cond :: [a] -> Bool
t    :: [a] -> [a]
f    :: [a] -> [a]

-- desired result
     :: [a] -> [a]

ここで、 any の代わりにiftefor を簡単に特殊化しました。関係は明らかです。、、およびの出力タイプはの入力タイプと一致します。これら 3 つの式すべてに同じものを与える必要があるだけです。それが適用可能であることを認識して、次のように一般化します。[a]acondtfifte[a](input ->)

arg1 :: (a -> b -> c -> d)
arg2 :: f a
arg3 :: f b
arg4 :: f c
res  :: f d

-- for our case,
-- f = ([a] ->)
-- a = Bool
-- b = [a]
-- c = [a]
-- d = [a]

やめて…フーグルタイム!Hoogling(a -> b -> c -> d) -> f a -> f b -> f c -> f dから、すぐに が見つかりますがliftA3、これは驚くほど定義されていません。

liftA3 f a b c = f <$> a <*> b <*> c
于 2011-10-22T23:11:32.183 に答える