在Haskell中,在处理ad hoc多态时,有很多高kinded多态的例子,如Monad和Functor。但是,我想不出参数多态的任何例子。
这是可能的,如果可以的话,我可以举一个有用的例子吗?
答案 0 :(得分:2)
如果您仍然允许类型类约束,那么答案是,确定!例如。我仍然会打电话给
<li><a href="{{ URL::to('/static/page/'.$page->page_id) }}">{{ $page->page_title }}</a></li>
参数多态。但我想这不是你的想法。
另一件显然可能的事情就是仅限制类型以具有特定形式normalise :: (Foldable f, Functor f, Fractional n) => f n -> f n
normalise v = fmap (/sum v) V
,例如
_ _
这并不是非常了不起,但它可能在某些应用程序中作为类型检查器的微妙提示。实际上,这是解决幻像参数问题的一种方法:而不是
hmap :: (f a -> f b) -> [f a] -> [f b]
hmap = map
你可以签名
class LengthyList l where minimumLength :: l a -> Int
instance LengthyList [] where minimumLength _ = 0
instance LengthyList NonEmpty where minimumLength _ = 1
又名
minimumLength :: p (l a) -> Int
因此,您仍然传递 minimumLength :: proxy (l a) -> Int
的类型信息,但保证实现不能尝试在运行时评估参数。
但要执行此操作的standard way是
l
minimumLength :: Tagged (l a) Int
一般来说, minimumLength :: Proxy (l a) -> Int
无法用f a
做任何事情,所以基本上你可以将任何这样的高阶参数函数的类型重写为第一个 - 命令参数多态。
答案 1 :(得分:2)
你完全可以做到这一点。类型同义词pigworker喜欢:
type f ~> g = forall a . f a -> g a
由于我实际上并不知道的原因,这代表了仿函数f
和g
之间的自然转换(无论是什么)。但是函数可以采用f ~> g
类型的参数,并将其应用于任意数量的f a
类型。使用非常规类型(特别是高阶嵌套数据类型,例如Ralf Hinze,在Numerical Representations as Higher-Order Nested Datatypes中探讨过),它可以应用于无限数量的不同类型。
一个人为的例子:
{-# LANGUAGE RankNTypes, TypeOperators #-}
type f ~> g = forall a . f a -> g a
data Two g a = Two (g a) (g a)
data Foo f a = This (f a)
| That (Foo (Two f) a)
hello :: (f ~> g) -> Foo f a -> Foo g a
hello t (This fa) = This (t fa)
hello t (That buh) =
That (hello (\(Two x y) -> Two (t x) (t y)) buh)
hello
在f
和g
类型中具有多态性,每种类型都有* -> *
种。 †我认为将此转换为仅使用类型*
可能需要进行非平凡的重构。
†事实上,如果您启用PolyKinds
,则f
和g
会分别采用多边形类型k -> *
。
答案 2 :(得分:1)
我非常喜欢的一个例子是p
运算符,用于按其长度索引的列表:它在类Nat -> *
的谓词m
上具有参数多态性,并保证如果您将其应用于长度为p m
的列表,则会返回foldr :: forall a (p :: Nat -> *).
(forall n. a -> p n -> p ('Succ n)) ->
p 'Zero ->
forall n. Vec a n -> p n
的证明。
这对应于这种类型:
append
这种额外的精度使得有可能实现例如foldr
使用append :: forall a m n. Vec a m -> Vec a n -> Vec a (m :+: n)
而非必须进行模式匹配。
{{1}}
我已上传a complete gist,其中包含所有正确的语言扩展程序以及与这些类型相对应的代码,以防您想要查看。