2013-03-15 93 views
2

我有一個函數,dir_con :: (Int -> Dir)模式匹配上功能

我想要模式匹配以找到具體的構造dir_con是。數據類型是:

data Dir = Define Int 
     | Equals Int 
     | Data Int 
     | LCset Int 
     | NoArg Int 

所以,dir_con要麼是定義,的Equals等,這是傳遞給函數的和我想的模式匹配,像這樣:

case dir_con of 
    NoArg -> Do something specific 
    _  -> Do something for the rest 

編譯器不像那樣。錯誤訊息是Couldn't match expected type 'Int -> Dir' with actual type 'Dir'

當然NoArg是類型(Int -> Dir)的構造函數? Haskell不允許這種類型的模式匹配嗎?我必須這樣做,因爲Dir構造函數來自地圖。有沒有關於如何以不同方式對待NoArg的建議?

+0

您可能需要重構您的數據類型以將當前構造器移動到枚舉中,例如,像'data Dir = Dir DirType Int;數據DirType =定義|等於|數據| LCset | NoArg'。 – hammar 2013-03-15 21:51:31

回答

4

您不能在功能上模式匹配。類型Dir的值通過應用幾個構造函數之一構建,但dir_con是類型Int -> Dir的函數。

你可能需要在模式匹配之前應用功能:

case dir_con 7 of -- `7` is just an arbitrary value I'm passing 
    NoArg _ -> ... 
    _  -> ... 

此外,你必須以匹配NoArg構造函數的參數爲​​好,否則你會加入後得到另一種類型的錯誤參數爲dir_con

在你的具體情況,你很可能不希望傳遞一個字面整數,但也許你從其他地方得到一個說法:

myfun n = ... case dir_con n of 
       NoArg _ -> ... 
       _  -> ... 
+0

一個簡單而優雅的解決方案。謝謝。 – DarthGazak 2013-03-16 21:09:50

5

兩種方式:

case dir_con of 
    NoArg _ -> Do something specific 
    _  -> Do something for the rest 

你匹配/價值/未構造函數。

或者,usingr記錄語法:

case dir_con of 
    NoArg {} -> Do something specific 
    _  -> Do something for the rest 

這是良好的衛生習慣,因爲它是中性的,對於字段的數量。

1

如果你的所有構造函數是Int -> Dir類型,那麼我建議一樣@hammar:使構造類型的枚舉:

data DirType = Define | Equals | Data | LCset | NoArg 

data Dir = Dir DirType Int 

那麼你也許可以重構任何需要知道它是使用的DirType的值,而不是有什麼構造函數。

試圖確定構造函數dir_con :: Int -> Dir是什麼的基本問題是,並非所有類型的構造函數都是構造函數。對於exampe:

dispatch :: Int -> Dir 
dispatch 0 = Define 0 
dispatch 1 = Equals 1 
dispatch n = NoArg n 

沒有很好的答案,你可以得到的「它的構造函數」 dispatch是。

如果Dir是參數

data Dir a = Define a | Equals a | Data a | LCset a | NoArg a 

然後有一個類型的Dir構造;即forall a. a -> Dir a(您需要{-# LANGUAGE RankNTypes #-}擴展才能使用這些類型)。這種類型不允許像檢查其論證的dispatch這樣的詭計。所以,如果您有:

dir_con :: forall a. a -> Dir a 

那麼你可以通過傳遞一個微不足道的值

case dir_con() of 
    ... 

即使你永遠只能幾乎使用Dir Int檢查它的構造函數,多態性可以讓你更用你的類型描述。