对于instance Alternative [],(<|>) = (++)。因此,我认为(<|>)是一种拼接器,导致了看似几乎通用的容器转换器:
-- (<|>) = generalization of (++)
(<|) :: Alternative f => x -> f x -> f x
x <| xs = pure x <|> xs
conv :: (Foldable t, Alternative f) => t x -> f x
conv = foldr (<|) empty实际上,我能够概括Data.List中的所有函数,下面是一些:
-- fmap = generalization of map
reverse :: (Foldable t, Alternative f) => t a -> f a
reverse = getAlt . getDual . foldMap (Dual . Alt . pure)
-- asum = generalization of concat
asumMap :: (Foldable t, Alternative f) => (a -> f b) -> t a -> f b -- generalization of concatMap
asumMap f = getAlt . foldMap (Alt . f)
splitAt :: (Foldable t, Alternative f, Alternative g) => Int -> t a -> (f a, g a)
splitAt n xs = let (_,fs,gs) = foldl' (\(i,z1,z2) x -> if 0 < i then (i-1,z1 . (x <|),z2) else (0,z1,z2 . (x <|))) (n,id,id) xs in (fs empty,gs empty)此外,这种类比还产生了一些有趣的新实例,例如函子和的工作应用函子(Data.Functor.Sum):
instance (Foldable f, Applicative f, Alternative g) => Applicative (Sum f g) where
pure = InL . pure
InL f <*> InL x = InL (f <*> x)
InL f <*> InR x = InR (conv f <*> x)
InR f <*> InL x = InR (f <*> conv x)
InR f <*> InR x = InR (f <*> x)
instance (Foldable f, Applicative f, Alternative g) => Alternative (Sum f g) where
empty = InR empty
InL x <|> _ = InL x
InR _ <|> InL y = InL y
InR x <|> InR y = InR (x <|> y)实际上,用这个类推来概括所有函数并创建新的实例,特别是对于列表操作来说,这是个好主意吗?
编辑:我特别关注模糊的返回类型。对于正常的列表操作,返回类型与其参数类型是可还原的。但是“通用”版本不是,因为必须显式指定返回类型。这个问题严重到足以把类比视为危险吗?(或者还有其他问题吗?)
编辑2:如果我完全理解foldl'的行为,那么通用splitAt的时间复杂度(如上图所示)必须是Θ(length xs),因为foldl'对每个元素都是严格的,对吧?如果是的话,那肯定是个问题,因为它不如普通版本的Θ(min n (length xs))。
发布于 2018-02-08 12:20:34
使函数在理论上尽可能具有多态性并不总是一个好主意,尤其是不使用函数参数。作为经验法则:使函数结果尽可能多态。(通常,参数将包含一些在结果中使用的类型变量。)只有当你有一个特定的原因,也给参数额外的多态。
原因是:如果一切都是多态的,编译器就不会提示要选择哪些具体类型。多态结果/值通常是正常的,因为这些结果/值通常直接或间接地绑定到具有显式签名的顶级定义中,但多态参数通常只使用文字填充(在Haskell中数字文字是多态的,字符串/列表也可以是多态的)或其他多态值,因此您最终不得不输入大量显式的本地签名,这往往比偶尔抛出显式转换函数更尴尬,因为某些东西不够多态。
这个关于Foldable->Alternative的想法特别有另一个问题,那就是Alternative类是不受欢迎的,没有非常坚实的数学基础。它基本上是应用函子的类,对每一个实例化都会产生一个Monoid。嗯,这也可以直接表达,要求Monoid本身。因此,“通用容器转换函数”已经存在,它是foldMap pure。
https://stackoverflow.com/questions/48680612
复制相似问题