2015-08-17 47 views
1

這裏是我的功能無法匹配打印嵌套列表的Haskell代碼中的預期類型?

data Item a = One a | Many [Item a] 
let flat (One x) = show x 
let flat (Many xs) = show xs 

這裏是輸出

Prelude> flat [[3]] 

<interactive>:21:6: 
Couldn't match expected type ‘Item t0’ with actual type ‘[[t1]]’ 
In the first argument of ‘flat’, namely ‘[[3]]’ 
In the expression: flat [[3]] 
In an equation for ‘it’: it = flat [[3]] 

它看起來像平坦的不承認項目作爲其函數簽名,所以我試圖重新定義函數簽名

flat :: Item a -> [a] 

<interactive>:22:1: 
    Couldn't match type ‘a1’ with ‘Char’ 
    ‘a1’ is a rigid type variable bound by 
     an expression type signature: Item a1 -> [a1] at <interactive>:22:1 
Expected type: Item a1 -> [a1] 
    Actual type: Item a1 -> String 
In the expression: flat :: Item a -> [a] 
In an equation for ‘it’: it = flat :: Item a -> [a] 

但Haskell不會讓你在ghci中重新定義函數簽名,有沒有辦法解決這個問題?

+1

我懷疑你的意思是'One a |許多[a]'。 – 9000

+4

難道你不想'平(多['3'])'?或者沒有類型簽名的'flat(Many [3])'。 – ErikR

+0

啊,這是意想不到的,我想我要做的是平坦化一個任意深度的嵌套列表(我正在通過打印出來的東西進行調試),我想我可以定義一個新的數據結構來做到這一點,但它似乎我實際上必須爲每個元素定義類型?這似乎破壞了目的。有沒有辦法模式匹配Many vs One – Kevin

回答

4

flat [[3]]產生一個類型錯誤。 [[3]]有類型Num a => [[a]],而不是Show a => Item a,您可以將其傳遞到flat

flat (Many [3])將返回"[3]"

+0

有沒有一種方法可以自動檢測'[3]'是多種類型而不明確定義它? – Kevin

+0

@Kevin你可以寫一個自定義的Read實現,並執行'flat。閱讀'(與指定的適當類型),但除此之外,不;你必須將它定義爲'Many [One 3]'來讓它通過'flat'。 – paul

1

回答你在@ jtobin的回答中提出的後續問題:是的,有一種方法可以自動檢測[3]需要包裝到Maybe構造函數中。但是你可能需要添加類型註釋(參見example幫助哈斯克爾弄清楚怎麼做=。

我們開始與一羣語言擴展。

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 
{-# LANGUAGE FlexibleInstances  #-} 

然後是你的Item定義。

module Item where 

data Item a = One a | Many [Item a] 

我們介紹一類的東西可以被具體化到Item a並宣佈兩個實例:在Many一個和基本情況你可以看到,我們現在有重疊instanc es(例如對於Itemable [Int] [Int]),所以你在這裏玩火。

class Itemable b a where 
    item :: b -> Item a 

instance Itemable b a => Itemable [b] a where 
    item = Many . fmap item 
instance Itemable a a where 
    item = One 

你終於可以定義flat,它可以使一個bItem a第一個函數,然後壓平它:

flat :: Itemable b a => b -> [a] 
flat = go . item where 
    go (One a) = [a] 
    go (Many as) = concatMap go as 

如下面的例子類型檢查和評估,以[2,43,7,8,1]顯示了哪些工作:

example :: [Int] 
example = flat [[[[[[2::Int],[43]],[[7],[8]],[[1]]]]]] 

但是,只要您嘗試使用重疊的實例,它會吹在你的臉上。例如:

example' :: [[Int]] 
example' = flat [[[[[[2::Int],[43]],[[7],[8]],[[1]]]]]] 
相關問題