2011-10-24 45 views
2

我圖案上記錄的數據構造的匹配,我有下面的代碼塊:使用匹配的值構建在Haskell

colorFor shape = 
    case material shape of 
    ColorMaterial -> material shape 
    -- etc. 

問題是這樣的:material是一個非平凡方法,我不想在案件陳述中重新計算它。我知道我可以做這樣的事情:

colorFor shape = 
    let m = material shape 
    in case m of 
    ColorMaterial -> m 

colorFor shape = 
    case material shape of 
    ColorMaterial r g b -> ColorMaterial r g b 

但我忍不住想必須有某種方式來檢索模式匹配匹配的值。這也適用於函數定義,我想在數據構造函數中匹配某個參數而不完全解壓縮它。

僅供參考:我是Haskell的新手,如果有更好的方法來做我正在做的事情,我非常樂於提供建議。任何幫助非常感謝!

回答

8

您正在尋找「as patterns」:

data SomeDataType = ColorMaterial Int Int Int 
        | BlandMaterial 

colorFor shape = 
    case material shape of 
    [email protected](ColorMaterial _ _ _) -> res 
    -- etc. 
+0

這裏的潛在問題是,你必須定義方式多個「模式」,一爲每次想立即返回,而不是一個讓數據類型。 – Phyx

+0

s/datatype/pattern – Phyx

+0

這確實是我正在尋找的東西,但Phyx關於它是如何被轉換爲'let'的說法已經說服我保持它原樣。謝謝! –

2

我真的不知道有任何‘更好’的方式做到這一點比

colorFor shape = 
    let m = material shape 
    in case m of 
     ColorMaterial -> m 

特別是在看什麼GHC用幹托馬斯建議運行ghc -ddump-ds的「as模式」顯示,ghc只是在解除後使其成爲一個let。

Main.colorFor :: forall t_ac9. t_ac9 -> Main.SomeDataType 
[LclId] 
Main.colorFor = 
    \ (@ t_ac9) -> 
    letrec { 
     colorFor_ac8 :: t_ac9 -> Main.SomeDataType 
     [LclId] 
     colorFor_ac8 = 
     \ (shape_aby :: t_ac9) -> 
      **let** { 
      res_abz :: Main.SomeDataType 
      [LclId] 
      **res_abz** = 
       GHC.Err.undefined @ (t_ac9 -> Main.SomeDataType) shape_aby } in 
      let { 
      fail_dcV :: GHC.Prim.State# GHC.Prim.RealWorld -> Main.SomeDataType 
      [LclId] 
      fail_dcV = 
       \ (ds_dcW :: GHC.Prim.State# GHC.Prim.RealWorld) -> 
       Control.Exception.Base.patError 
        @ Main.SomeDataType "Test.hs:(5,3)-(6,36)|case" } in 
      case res_abz of wild_B1 { 
      __DEFAULT -> fail_dcV GHC.Prim.realWorld#; 
      **Main.ColorMaterial ds_dcS ds_dcT ds_dcU -> res_abz** 
      }; } in 
    colorFor_ac8 

這是相當詳細的,但我已經用<>標記了重要部分。未定義的是因爲「材料」不存在於我的代碼中,我需要它在那裏編譯。所以As-Pattern只有當它只有一個時才更好。還有,你最好讓自己放手。減少打字和看起來更好imho。

這似乎一般也持有:

data SomeDataType = ColorMaterial Int Int Int 
        | BlandMaterial 
        | NoMaterial 

colorFor shape = 
    case undefined shape of 
    [email protected](ColorMaterial _ _ _) -> res 
    [email protected]   -> foo 

只是引入了另一個讓,而不僅僅是有一個已任更多的輸入。

Main.colorFor :: forall t_ace. t_ace -> Main.SomeDataType 
[LclId] 
Main.colorFor = 
    \ (@ t_ace) -> 
    letrec { 
     colorFor_acd :: t_ace -> Main.SomeDataType 
     [LclId] 
     colorFor_acd = 
     \ (shape_abz :: t_ace) -> 
      let { 
      **res_abA** :: Main.SomeDataType 
      [LclId] 
      **res_abA** = 
       GHC.Err.undefined @ (t_ace -> Main.SomeDataType) shape_abz } in 
      let { 
      fail_dd0 :: GHC.Prim.State# GHC.Prim.RealWorld -> Main.SomeDataType 
      [LclId] 
      fail_dd0 = 
       \ (ds_dd1 :: GHC.Prim.State# GHC.Prim.RealWorld) -> 
       Control.Exception.Base.patError 
        @ Main.SomeDataType "Test.hs:(6,3)-(8,36)|case" } in 
      **let** { 
      foo_abB :: Main.SomeDataType 
      [LclId] 
      **foo_abB** = res_abA } in 
      case res_abA of wild_B1 { 
      __DEFAULT -> fail_dd0 GHC.Prim.realWorld#; 
      Main.ColorMaterial ds_dcX ds_dcY ds_dcZ -> res_abA; 
      Main.BlandMaterial -> foo_abB 
      }; } in 
    colorFor_acd