简体   繁体   English

Haskell:应用多态函数两次

[英]Haskell: apply a polymorphic function twice

We can have a polymorphic function f :: a -> b implemented for different pairs of a and b . 我们可以为不同的ab对实现多态函数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 -> bf :: 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM