簡體   English   中英

基本類型的模式匹配

[英]Pattern matching on basic types

這是我想要的:

f n = case n of
  String -> "string"
  _ -> "other"

或者其他的東西。 如果要用字符串調用,我希望f映射到原義的“字符串”,否則應映射為“其他”。 這不能像我正在做的那么難。

如果您來自JS和Python,那是可以理解的,您認為這應該可行–畢竟,在這些語言中,類型本質上是值的特定屬性。 但這根本不是Haskell類型系統如何工作的! 實際上,類型和值屬於完全獨立的“ Universe”:類型僅在編譯時存在,值僅在運行時存在。 確實每個值都屬於一個類型,但是此信息在編譯時已被完全解析。 在運行時,通常不必分派類型,因為編譯器已經提前進行了分配,並且永遠不可能傳入有效值以外其他類型的值。因此,這總是多余的。 實際上在運行程序之前, 已刪除類型信息
因此,從直接的意義上說,您要實現的目標確實是不可能的。 或者,憤世嫉俗地說,這很簡單

f :: String -> String
f _ = "string"

通常,如果您發現自己想在類型上進行運行時分派,則表明您可能首先應該使用變體類型:

data StringOrInt = It'sAString String | It'sAnInt Int

f :: StringOrInt -> String
f (It'sAString _) = "string"
f (It'sAnInt _) = "int"

...理想地使用更具描述性的,特定於應用程序的名稱。

這就是說,它實際上可以在Haskell的“動態類型”的值,比如在Python。 您只需要請求包含類型信息的包裝器,否則編譯器會在運行時刪除這些信息:

{-# LANGUAGE TypeFamilies #-}

import Data.Dynamic
import Type.Reflection

f :: Dynamic -> String
f (Dynamic t _)
   = case eqTypeRep t (typeOf "string") of
       Just HRefl -> "string"
       _          -> "other"

用法示例:

main = do
   putStrLn . f $ toDyn "bla"
   putStrLn . f $ toDyn True
   putStrLn . f $ toDyn 'y'

屈服

string
other
other

與笨拙的eqTypeRep構造相比,寫f更優雅的方式是

f :: Dynamic -> String
f s = case fromDynamic s :: Maybe String of
       Just _ -> "string"
       _      -> "other"

通常,在Haskell中像這樣的臨時多態性和類型自省是不受歡迎的。 仍然有可能,但是有點脆弱:

{-# LANGUAGE FlexibleInstances #-}

class F a where
  f :: a -> String

instance F String where
  f n = "string"

instance {-# OVERLAPPABLE #-} F other where
  f n = "other"

另外,您可以使用不太脆弱的Typeable ,但需要從調用方獲取實例:

import Data.Typeable

f :: Typeable a => a -> String
f n = if typeOf n == typeOf "" then "string" else "other"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM