I know the title is a bit unclear, the problem is:
Suppose I have a function of type a -> c
, another function of type b -> d
, how can I get a function of type (a -> b) -> (c -> d)
, or is it impossible in general?
Probably I should provide some background. I asked this question because I have difficulty solving Exercise 9 from the paper Fun with phantom types.
data Type t where
...
RFun :: Type a -> Type b -> Type (a -> b)
And the tequal
function
tequal :: Type t -> Type u -> Maybe (t -> u)
...
tequal (RFun a b) (RFun c d) = -- should do something with (tequal a c) (tequal b d)
So the problem boils down to composing a -> c
and b -> d
to get (a -> b) -> (c -> d)
答案 0 :(得分:3)
这是不可能的。
假设您有所需的功能f :: (a -> b) -> (c -> d)
。
您可以将其类型简化为(a -> b) -> c -> d
(请参阅why)。
f
的实现怎么样?它的第一个参数类型为a -> b
,第二个类型为c
:
f ab c = ...
你可以用ab
做什么?这是一个函数,但您无法应用它,因为您没有a
类型的任何内容(_|_
除外)。即使您有g :: a -> c
和h :: b -> d
函数,它们也没用,因为您没有a
或b
类型的任何内容,而且您无法撰写它们。
所以唯一有效的实现类似于
f ab = undefined
或
f = undefined
关于问题的第二部分,您似乎可以递归使用tequal
检查函数类型是否相等:类型a -> c
和b -> d
仅在a
=时相等b
和c
= d
(这是有效的,因为论文中的玩具类型系统没有类型变量)。
以下是实施草图:
tequal (RFun a c) (RFun b d)
= liftM2 func (tequal a b) (tequal c d)
您可以注意到代码几乎与RPair
的情况相同。这与currying有某种关系。
答案 1 :(得分:3)
作为max taldykin答案的一个小补充,
鉴于
f :: (a -> c) -> (b -> d) -> (a -> b) -> (c -> d)
f ac bd ab = ???
实际上只有一种方法可以合并参数
bd . ab :: a -> d
但现在我们被困住了!我们无法从c -> d
,a -> c
,b -> d
或a -> b
的任意组合构建a -> d
。
另一方面,如果我们有一个c -> a
,那么我们可以构建一个
f :: (c -> a) -> (b -> d) -> (a -> b) -> (c -> d)
f ca bd ab = bd . ab . ca
顺便说一句,拿出笔和纸并绘制一些箭头并尝试将它们连接到图表中会非常有帮助:
如果您尝试对f :: (a -> c) -> (b -> d) -> (a -> b) -> (c -> d)
执行相同操作,那么您将看到无法绘制连接c -> d
的图表:
现在我们无法连接点。
答案 2 :(得分:0)
我相信您正在寻找高阶函数,这基本上是一个将函数作为参数或返回其他函数的函数。
例如,为了说明更高阶函数,您可以定义以下函数:
f0 :: Int -> Int
f0 x = 0
f1 :: a -> a
f1 x = x
f2 :: (a -> a) -> a -> a
f2 f a = f(a)
f3 :: (a -> a) -> (a -> a)
f3 f = f1
请注意,f2采用函数并将其应用于第二个参数,f3采用函数,返回函数f1。< / p>
如果执行f2(f3(f0))5,它将返回5给你。
<强>步骤一步强>
1- f2(f3(f0))5 f3取一个函数(f0)并返回f1。
2- f2(f1)5 f2取一个函数(f1)并将其应用于第二个参数(5)
3- f1(5) f1适用于5.