使用一个高级类型和两个嵌套类型折叠两个元素的Generalize函数?

时间:2017-07-07 15:34:36

标签: haskell polymorphism composition higher-kinded-types

我接下来有两个要素:

x :: Maybe t
y :: [(String, t)]

我有一个功能:

foo :: t -> a

如何实现可以在xy上使用foo同时在列表中收集结果的多态函数?更具体地说,我需要在这里添加一些代替???的东西:

mapToList :: ??? => (t -> a) -> ??? t -> [a]

我希望用更少的样板来调用,最优选的选项最好:

mapToList foo x
mapToList foo y
像这样天真的东西不起作用:(

mapToList :: Foldable f => (t -> a) -> f t -> [a]
mapToList extractor = map extractor . toList

mapToList @Maybe             foo x
mapToList @([] ((,) String)) foo y

我在看Get user membership groups in the claims with AD B2C,但没有设法弄清楚如何以简单的方式将它应用到我的问题中。我可以使用Compose来概括以某种方式,但我的解决方案并不令人满意。我可以随时使用map列表,maybe [] foo只使用Maybe。但是我想知道,有没有很好的方法来推广这两个用例?

1 个答案:

答案 0 :(得分:1)

不确定这有什么用处,因为它只是将样板移离呼叫站点,但是:

{-# LANGUAGE FlexibleInstances,FunctionalDependencies,RankNTypes #-}

import Data.Functor.Compose (Compose(Compose))
import Data.Foldable

class AsFoldable x a | x -> a where
  withFoldable :: (forall f. (Foldable f) => f a -> b) -> x -> b

instance AsFoldable [(String,a)] a where
  withFoldable f = f . Compose

instance AsFoldable (Maybe a) a where
  withFoldable = id

x :: Maybe Int
x = Just 3

y :: [(String,Int)]
y = [("A",5),("B",6)]

mapToList :: (AsFoldable x t) => (t -> a) -> x -> [a]
mapToList f = withFoldable (map f . toList)

main = do
  print $ mapToList (+1) x
  print $ mapToList (+1) y