Haskell “的正式定义;“一元函数”;
维基上说: 一元函数(即使用单元值作为 它们的参数或返回值) 我的理解是一个函数接受或返回一个单子就是一元函数,但当我遇到这个问题时,它的定义似乎更严格 作者说: 一元函数是产生一元值的函数。(注 我们没有提到它的输入类型) 及 函数的形式为Haskell “的正式定义;“一元函数”;,haskell,functional-programming,monads,Haskell,Functional Programming,Monads,维基上说: 一元函数(即使用单元值作为 它们的参数或返回值) 我的理解是一个函数接受或返回一个单子就是一元函数,但当我遇到这个问题时,它的定义似乎更严格 作者说: 一元函数是产生一元值的函数。(注 我们没有提到它的输入类型) 及 函数的形式为f::a->mb,其中a是 单子的内部值。(称这些为经典的一元函数) 表单f::anything->mb的函数,其中 功能真的不重要。(称这些为松散的一元函数) 看起来这个定义很严格,很正式,但我找不到任何地方可以说明 那么到底什么是一元函数呢?我知道你提到
f::a->mb
,其中a
是
单子的内部值。(称这些为经典的一元函数)
表单f::anything->mb
的函数,其中
功能真的不重要。(称这些为松散的一元函数)
看起来这个定义很严格,很正式,但我找不到任何地方可以说明
那么到底什么是一元函数呢?我知道你提到了 在您的上下文中,“一元函数”指定要编写更大函数的函数,利用
(>>=)
和返回所做的隐式上下文处理
示例:假设您有一个Map
的Map
s来表示4个组合的输出值
“aa”->1,“ab”->2,“bc”->3,“bd”->4
表示lookup::ordk=>k->mapka->可能是a
这里查找
是所谓的“一元函数”,它必须组成(在这里与自身一起)才能给出类型的函数:Char->Char->Map2->Maybe Int
composedLookup a b m = do
v <- lookup a m
v' <- lookup b v
return v'
编辑:
而ma->b
类型的函数在m
是一个comonad的上下文中被称为comonadic。
我发现这很有启发性,因为它最终从类型和应用的角度解释了monad和comonad
希望这有助于让我们研究一下在函数的输入或输出中使用monad的可能性
其中一个输入参数中的Monad:f::ma->X
。因为对于我们拥有的任何monadreturn::a->ma
,我们都可以用f组合它并得到
f . return :: a -> X
纯输出:f::X->b
。通过将它与来自另一边的返回进行组合,我们得到
return . f :: X -> m b
所以我们总是可以把一个纯输出转换成一元输出,把一元输入转换成纯输出。任何具有纯或一元输入/输出的函数都可以转换为形式
f :: a1 -> ... -> an -> m b
然而,反过来是不可能的(一般来说)
我要说的是,“经典”和“松散”一元函数没有广泛使用。一个简短且(我希望)简单的答案是,一元函数的返回数据签名/类型与其输入数据签名/类型相同
想象一下加号运算符的功能:
def plus(a,b):
return a+b
这不是一元的,因为它接受一个元组,但返回一个值
但改写为:
def monad_plus(a,b):
if b is None:
return (a, None)
else:
return (a+b, None)
然后,该函数的结果可以输入到另一个函数调用中,而无需任何更改
然后,您可以创建一系列函数,这些函数既接受(a,b)
输入,又返回相同的(a,b)
输出
def monad_mult(a,b):
if b is None:
return (a, None)
else:
return (a*b, None)
def monad_div(a,b):
if b is None:
return (a, None)
else:
return (a/b, None)
我认为,实际上,您应该处理退化情况,其中a○ None
不应该对a
执行任何更改,这就是为什么我明确添加了那些if is None
测试的原因,但我欢迎对此提供建议
实际的最终结果应该是,您能够将这些调用的整个集合串在一起,并提交它们的执行以多种方式执行-串行、分布式等,成批或按顺序对数据集执行,并且始终保持信心返回相同的结果。文章顶部指出了在其他地方找不到这些术语的主要原因,其中指出:它包含了我个人和直觉的一元函数思维方式“一元函数”不是一个严格定义的术语。一元函数是严格定义的,一元函数不是。如果你的意思是a->mb
,你可以说Kleisli arrow或monadic function。您可以调用ma->mb->mc
一元函数。这取决于上下文,恐怕没有确切的答案。如果我们只知道这与你有什么关系,也许我们可以帮助你更好。请注意,我们讨论的是定义。每个人都可以自由定义他认为合适的术语。平心而论,一旦确定了某个术语,坚持自己的不同定义是不明智的。但是,正如你所说,你没有发现这些术语被广泛使用,因此要么从你引用的博客中继承定义,要么提出自己的定义。这种“经典”一元函数和“松散”一元函数之间的区别并没有很好的定义。没有“单子的内在价值”这样的东西。我不会把这篇博文看得太重。我们都喜欢分享我们发现新概念的旅程,但这并不意味着我们对旅程的理解会对其他人有所帮助,或者包含定义良好的标准概念。我会称a->mb
a Kleisli箭头和ma->b
a Cokleisli箭头。前者通常与单子相连,而后者通常更与单子相连。这样我们可以避免模糊的术语,这可能会引起一些混乱。请注意Kleisli箭头如何适合>=
(bind)Monad方法,以及Cokleisli箭头如何适合extend
(aka我认为MA->b
类型的函数只有在m
是一个comonad时才能合理地称为comonadic。我的错了,谢谢你的更正。答案按照编辑。
def monad_plus(a,b):
if b is None:
return (a, None)
else:
return (a+b, None)
def monad_mult(a,b):
if b is None:
return (a, None)
else:
return (a*b, None)
def monad_div(a,b):
if b is None:
return (a, None)
else:
return (a/b, None)