繁体   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