tor*_*tte 4 haskell functional-programming idris
我想我在写出步骤时理解了函数应用程序的工作原理,但类型签名算术并没有在我的脑海中相加。对冗长的前奏表示歉意(没有双关语)。
\n举一个具体的例子,这个例子是Stefan H\xc3\xb6ck\ 的 Idris2 教程的一个稍微修改过的例子:
\nplusTwo : Integer -> Integer\nplusTwo = (+2)\n\ntwice : (Integer -> Integer) -> Integer -> Integer\ntwice f n = f (f n)\n
Run Code Online (Sandbox Code Playgroud)\n在 REPL 中:
\n> twice plusTwo 3\n7\n\n> (twice . twice) plusTwo 3\n11\n
Run Code Online (Sandbox Code Playgroud)\nHaskell 和 Idris 中的函数都是柯里化的,每个函数只接受一个参数
\n函数组合实现为
\nf . g = \\x -> f (g x)\n
Run Code Online (Sandbox Code Playgroud)\n函数应用程序是左关联的
\n类型签名中的箭头是右关联的
\n(twice . twice) plusTwo 3
该表达式可以显式地用括号表示为
\n((twice . twice) plusTwo) 3\n
Run Code Online (Sandbox Code Playgroud)\n可以重写为
\n ------f-------- -n-\n(twice (twice plusTwo)) 3\n |\n V\n------f-------- (------f-------- -n-)\n(twice plusTwo) ((twice plusTwo) 3 )\n \\------------------/\n |||\n plusTwo (plusTwo 3)\n |||\n 7 \n\\-----------------------------------/\n |||\n twice plusTwo 7\n
Run Code Online (Sandbox Code Playgroud)\n下面的函数组合运算符的类型签名显示它采用单参数函数,
\n(.) :: (b -> c) -> (a -> b) -> a -> c\nf . g = \\x -> f (g x)\n
Run Code Online (Sandbox Code Playgroud)\n但twice
需要两个参数(即(t -> t) -> t -> t
),所以这让我失望。
x
我想当返回的 lambda 的参数本身就是一个函数时,这是唯一可行的方法。事情有这么简单吗?
twice . twice\n((a -> a) -> a -> a) -> ((a -> a) -> a -> a) -> ?\n\n(---b---- -> --c---) -> (---a---- -> --b---) -> (a -> c)\n\n? = (a -> a) -> a -> a\n
Run Code Online (Sandbox Code Playgroud)\n或者,换句话说,twice . twice
采用带有签名的函数(a -> a) -> a
(a
这里是Integer
)。
如果上述内容是正确的,那么我可以找出参与函数具有不同输入参数(例如twice . (+2)
)的函数组合。
是的,仅此而已。twice
如果你写下as的签名,可能会更容易思考
twice :: (Integer -> Integer) -> (Integer -> Integer)
Run Code Online (Sandbox Code Playgroud)
如您所知,这相当于柯里化。从这个角度来看,twice
是一个参数的函数,并且twice
再次组合它似乎是完全明智的。
归档时间: |
|
查看次数: |
232 次 |
最近记录: |