我是函数式编程的新手,我正在尝试解决以下问题;
给出类型
$secret = '6LclC3QUAAXXXXXXXXXXXXXXXX5hrAxfHXXXiMH';
$response = $_POST['g-recaptcha-response'];
$remoteip = $_SERVER['REMOTE_ADDR'];
$data = array(
'secret' => $secret,
'response' => $response,
'remoteip' => $remoteip
);
$options = array(
'http' => array(
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$res = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, $context), true);
实现以下高阶函数
type Cont r a = (a -> r) -> r
第一步是简化类型,从而得出:
mapReader :: (a -> b) -> (Cont r a) -> Cont r b
接下来,定义此功能中需要提供的参数。这些参数是三个函数,所以我们得到
mapReader :: (a -> b) -> ((a -> r) -> r) -> (b -> r) -> r
从这里,我们可以定义以下类型:
mapReader :: (a -> b) -> ((a -> r) -> r) -> (b -> r) -> r
mapReader f g h = _1
但是现在我被卡住了。有两个产生r的函数,其中一个包含另一个函数(a-> r)。如何开始定义r?任何提示都非常感谢!
答案 0 :(得分:5)
我们有
f :: a -> b
g :: (a -> r) -> r
h :: b -> r
我们需要
_1 :: r
我们可以通过两种方式制作r
:g
和h
。
让我们尝试使用h
。 h
接受类型为b
的参数。获得其中之一的唯一方法是使用f
。 f
接受类型为a
的参数,并且...我们无法获得其中之一。
因此,现在让我们尝试使用g
代替:
mapReader f g h = g _2
被告知
_2 :: a -> r
由于我们正在构造函数,因此可以照常应用lambda抽象:
mapReader f g h = g (\a -> _3)
a :: a
_3 :: r
但是等一下...现在我们有一个a
,所以我们可以回到第一次尝试:
mapReader f g h = g (\a -> h (f a))
或更紧凑地说,
mapReader f g h = g (h . f)
如果不是重新尝试第一次尝试,而是再次使用第二种方法 呢?
mapReader' f g h =
g (\a1 -> g (\a2 -> _4))
_4 :: r
您可以永远这样,但也可以通过两种不同的方式在这里停留:
mapReader2 f g h =
g (\_ -> g (h . f))
mapReader3 f g h =
g (\a1 -> g (\_ -> h (f a1)))
好!这是三个具有不同类型的 different 函数,如图所示,该方法可用于生成无限的函数族!您如何确定想要哪一个?您必须考虑意图。 g
的论点是连续性,因此您想用传递的内容g
来构成一个函数,而不是多次调用g
。因此mapReader
是“正确”的答案。
更准确地说,mapReader
应该映射连续性 functor 的形态射影。尤其需要
mapReader id = id
也就是说,
mapReader id g h = g (h . id)
= g h
对于正确的定义,这是无条件的,但对于其他任何定义都不是。
答案 1 :(得分:1)
首先查看您可以使用这三个参数做什么。
f
和h
:h . f :: a -> r
。g
应用于h . f
:g (h . f) :: r
。所以您可以简单地说mapReader f g h = g (h . f)
。这里没有足够的信息来指定r
是什么。这完全取决于什么
自变量g
和h
被赋予mapReader
。
答案 2 :(得分:0)
所以你有
f :: a -> b
h :: b -> r
g :: (a -> r) -> r
还有前向功能组合运算符,
(>>>) :: (a -> b) -> (b -> r) -> (a -> r)
和反向应用程序运算符,
(&) :: t -> (t -> r) -> r
这样
f >>> h :: ......... -- what?
和
(f >>> h) & g :: ......... -- what else?
您能仅根据它们的类型来提出(>>>)
和(&)
的定义吗?
让我让您开始第一个。
(>>>) :: (a -> b) -> (b -> r) -> (a -> r)
表示
(>>>) (f :: a -> b) :: (b -> r) -> (a -> r)
(>>>) (f :: a -> b) (g :: b -> r) :: (a -> r)
(>>>) (f :: a -> b) (g :: b -> r) (x :: a) :: r
所以我们再次写下来
f :: a -> b
g :: b -> r
x :: a
f x :: b
g (f x) :: ....
就是这样。
我们在这里使用的最重要的规则是
x :: a
f :: a -> r
f x :: r