簡體   English   中英

haskell中的多態函數列表?

[英]List of polymorphic functions in haskell?

請考慮以下代碼:

t1 :: [Int] -> (Int,String)
t1 xs = (sum xs,show $ length xs)

t2 :: [Int] -> (Int,String)
t2 xs = (length xs, (\x -> '?') <$> xs)

t3 :: [Int] -> (Char,String)
t3 (x:xs) = ('Y',"1+" ++ (show $ length xs))
t3  []     = ('N',"empty")

這三個函數的類型只是部分變化 - 它們完全可用,而不需要知道它們產生的元組的第一個組件的類型。 這意味着我可以對它們進行操作而無需引用該類型:

fnListToStrs vs fs = (\x -> snd $ x vs) <$> fs

將這些定義加載到GHCi中,所有這三個函數都作為fnListToStrs的參數獨立工作,實際上我可以傳入包含t1和t2的列表,因為它們具有相同的類型:

*Imprec> fnListToStrs [1,2] [t1,t2]
["2","??"]
*Imprec> fnListToStrs [1,2] [t3]
["1+1"]

但我無法同時傳遞所有3個,即使類型的分歧實際上與執行的計算無關:

*Imprec> fnListToStrs [1,2] [t1,t2]
["2","??"]
*Imprec> fnListToStrs [1,2] [t3]
["1+1"]

我覺得使這項工作與存在性或不可預測的類型有關,但是當使用我期望fnListToStrs能夠采用的類型聲明時,這兩種擴展都不適用於我,即:

fnListToStrs :: [Int] -> [forall a.[Int]->(a,String)] -> [String]

有沒有其他方法使這項工作?

將這些函數放入列表的任何方法都需要以某種方式“包裝”它們。 最簡單的包裝就是

wrap :: (a -> (b, c)) -> a -> c
wrap f = snd . f

實際上還有其他方法來包裝這些(特別是存在類型),但是你沒有給出任何信息來暗示這些信息在你的應用程序中會比這個最簡單的版本稍微好一些。

這是一個更復雜的東西可能有意義的例子。 假設你有

data Blob a b = Blob [a -> b] [a]

現在假設你想要列出一個類型為Blob ab的值列表,它們都具有相同的b類型,但可能有不同a類型。 實際上將每個函數應用於每個參數可能會導致一個非常大的潛在結果列表,因此編寫它是有意義的

data WrapBlob b where
  WrapBlob :: Blob a b -> WrapBlob b

現在,您可以制作列表並推遲決定哪些函數適用於哪個參數而無需支付高昂的價格。

存在是正確的,而不是不可預測的。 並且Haskell沒有存在,除非通過一個明確的包裝器......

{-# LANGUAGE GADTs #-}

data SomeFstRes x z where
  SFR :: (x -> (y,z)) -> SomeFstRes x z

> fmap (\(SFR f) -> snd $ f [1,2]) [SFR t1, SFR t2, SFR t3]
["2","??","1+1"]

但是,這真的有點無用。 既然你不可能對第一個結果做任何事情,那么立即將它扔掉並將剩下的函數放在一個簡單的單態列表中更為明智:

> fmap ($[1,2]) [snd . t1, snd . t2, snd . t3]
["2","??","1+1"]

暫無
暫無

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

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