[英]Haskell: apply a polymorphic function twice
We can have a polymorphic function f :: a -> b
implemented for different pairs of a
and b
. 我们可以为不同的
a
和b
对实现多态函数f :: a -> b
b
。 How can we make 我们怎么做
twice :: (a -> b) -> a -> c
twice f x = f (f x)
type check? 型号检查? ie how can I write a function which applies a polymorphic function twice?
即如何编写一个两次应用多态函数的函数?
With Rank2Types
we can get a bit closer but not quite there: 使用
Rank2Types
我们可以更接近,但不是那里:
{-# LANGUAGE Rank2Types #-}
twice1 :: (forall a. a -> (m a)) -> b -> (m (m b))
twice1 f = f . f
twice2 :: (forall a. m a -> a) -> m (m b) -> b
twice2 f = f . f
so then some polymorphic functions can be applied twice: 那么一些多态函数可以应用两次:
\> twice1 (:[]) 1
[[1]]
\> twice2 head [[1]]
1
Can we go further? 我们可以走得更远吗?
The question was asked over Haskell cafe 10 years ago but wasn't quite answered (with type classes it becomes a lot of boilerplate). 问题是 10年前 在Haskell咖啡馆被问到的,但是没有得到很好的解答(类型等级它变成了很多样板)。
{-# LANGUAGE TypeFamilies, RankNTypes, UnicodeSyntax #-}
type family Fundep a :: *
type instance Fundep Bool = Int
type instance Fundep Int = String
...
twice :: ∀ a . (∀ c . c -> Fundep c) -> a -> Fundep (Fundep a)
twice f = f . f
Now, that won't be much use actually because you can't define a (meaningful) polymorphic function that works with any c
. 现在,这实际上没有多大用处,因为你无法定义一个适用于任何
c
的(有意义的)多态函数。 One possibility is to toss in a class constraint, like 一种可能性是抛出类约束,比如
class Showy a where
type Fundep a :: *
showish :: a -> Fundep a
instance Showy Bool where
type Fundep Bool = Int
showish = fromEnum
instance Showy Int where
type Fundep Int = String
showish = show
twice :: ∀ a b . (Showy a, b ~ Fundep a, Showy b) =>
(∀ c . Showy c => c -> Fundep c) -> a -> Fundep b
twice f = f . f
main = print $ twice showish False
You can't make twice
generic enough even in a dependently typed setting, but it's possible with intersection types: 即使在依赖类型的设置中,也不能使
twice
通用性足够,但是可以使用交集类型:
twice :: (a -> b /\ b -> c) -> a -> c
twice f x = f (f x)
Now whenever f :: a -> b
and f :: b -> c
typecheck, twice
will typecheck too. 现在每当
f :: a -> b
和f :: b -> c
typecheck时, twice
也会进行类型检查。
There is also a beautiful spell in Benjamin Pierce's thesis (I changed the syntax slightly): 本杰明·皮尔斯的论文中也有一个美丽的咒语(我略微改变了语法):
self : (A /\ A -> B) -> B
self f = f f
So self-application is typeable with intersection types as well. 因此,自我应用程序也可以使用交集类型进行类型化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.