2011-10-22 119 views
0

compress [email protected](_:_:_) = (ifte <$> ((==) <$> head <*> head.tail) <$> ((compress.).(:) <$> head <*> tail.tail) <*> ((:) <$> head <*> compress.tail)) xs爲什麼不這種類型檢測?

結果在類型錯誤,但我不明白爲什麼。它應該是相當於

compress [email protected](_:_:_) = (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 [email protected](_ : _ : _) 
      = (ifte <$> ((==) <$> head <*> head . tail) 
     <$> 
      ((compress .) . (:) <$> head <*> tail . tail) 
     <*> 
     ((:) <$> head <*> compress . tail)) 
      $ xs 

我遇到這個問題想寫一個pointfree解決Ninety-Nine Haskell Problems的問題8。我試圖通過修改貼題的解決方案我寫,這是

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

能否請您粘貼類型的錯誤,也許是代碼的少點的版本? – fuz

+4

對不起。你給我們提供了大量的無意義和不透明的代碼來解密,甚至沒有提到代碼的目的或任何細節,比如你得到的確切錯誤。我們應該如何幫助你? -1。 – fuz

+1

-1。這是一個典型的情況,需要喝一杯水,並且想一個人真正在做什麼。 – Tarrasch

回答

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:[email protected](y:_)) = ifte (x==y) id (x:) $ compress r 

或免積分

compress = map fst . filter (uncurry (/=)) . (zip <$> id <*> tail) 
+3

甚至'compress =地圖頭。組「 – sdcvvc

+1

此外,您的最後一個無點代碼刪除列表的最後一個元素,也許這不是OP想要的。 – sdcvvc

+0

與衆不同嗎?原始代碼缺少有限列表的基本案例,所以我不擔心尾部。 – Brandon

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 [email protected](_:_:_) = (ifte <$> u <$> v <*> w) xs 
compress [email protected](_:_:_) = (ifte (u xs) (v xs) (w xs)) 

我希望你現在看到的錯誤代碼 - 正確版本爲

--compress [email protected](_:_:_) = (ifte <$> u <*> v <*> w) xs 
+0

+1爲了解決一個可怕的問題,並使其有用 –

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 

在這裏,我把它分解出來,並作爲布蘭登提到的,在這一點上,你應該看到的是,錯誤在於採用<$>其中<*>應該的。您將獲得舒適與概念,你不斷地學習應用性的風格,你的表情通常有一個單一的<$>遵循<*>任意#:

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

忽略了見識,不過,我已經給這裏的每個子表達式類型和頂級域名(TLD)。這使我可以將文件加載到ghci中並播放一段時間。

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

WTF ???這是類型的聲音?它應該給出一個錯誤,但顯然這個表達是一個 - 好的。或者是?請注意,此類型簽名與我們想要的compress不符。

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

的子表達式匹配,我們希望他們,由編譯器不嘔吐對我們證明類型簽名。既然如此,那麼問題顯然就在於我們將它們結合起來。那麼我們想在這裏結合哪些部分?忽略公式約束:

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

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

在這裏,我做的ifte瑣碎專業化爲[a],而不是任何a。關係很明確:cond,tf的輸出類型匹配ifte的輸入類型。我們只需要餵飽所有這三個表達式[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 
相關問題