“monadic function”的正式定义

时间:2014-02-18 15:09:22

标签: haskell functional-programming monads

维基说:

  

monadic函数(即使用monad值的函数   他们的论点或回报值。)

我的理解是一个函数接受或返回monad是monadic函数,但是当我遇到这个blog

时它似乎有更严格的定义

作者说:

  

monadic函数是一个产生monadic值的函数。 (注意   我们没有说它的输入类型)

  

表单f :: a -> m b的功能,其中a是表单的类型   monad的内在价值。 (称这些经典的monadic函数)

     

表单f :: anything -> m b的函数,其中输入   功能真无所谓。 (称这些松散的monadic函数)

似乎这个定义非常严格和正式,但我找不到任何关于classic monadic functionsloose monadic functions的内容。

那么monadic函数究竟是什么?

3 个答案:

答案 0 :(得分:1)

我理解您参考this article in Wikipedia

在您的上下文中,“monadic functions”指定您可以编写的函数来编写更大的函数,利用(>>=)return完成的隐式上下文处理。

示例:假设您有MapMap来表示4种组合的输出值 “aa” - > 1,“ab” - > 2,“bc” - > 3,“bd” - > 4

import Data.Map (Map, lookup, fromList)

type Map1 = Map Char Int
v1 = fromList [('a',1),('b',2)]    :: Map1
v2 = fromList [('c',3),('d',4)]    :: Map1

type Map2 = Map Char Map1
myMap = fromList [('a',v1),('b',v2)]   :: Map2

Your best friend Hooglelookup :: Ord k => k -> Map k a -> Maybe a

此处 lookup是所谓的“ monadic function ,必须组合(此处为自身)以提供类型{{1 }}

:: Char -> Char -> Map2 -> Maybe Int

composedLookup a b m = do     
        v  <- lookup a m
        v' <- lookup b v
        return v'

编辑: 类型为composedLookup' a b m = lookup a m >>= (lookup b) 的函数在m a -> b作为comonad 的上下文中称为comonadic 。 我发现this great SO answer about algebra/coalgebra非常具有启发性,因为它最终在类型和应用方面解释了monad和comonads。

希望这有帮助

答案 1 :(得分:1)

让我们研究在函数的输入或输出中使用monad的可能性。

  1. Monad在其中一个输入参数中:f :: m a -> X。因为对于任何monad我们都有return :: a -> m a,我们可以用f组合它并获得

    f . return :: a -> X
    
  2. 纯输出:f :: X -> b。通过将它与来自另一方的返回组合起来,我们得到了

    return . f :: X -> m b
    
  3. 因此,我们总是可以将纯输出转换为monadic输出,将monadic输入转换为纯输出。任何具有纯或一元输入/输出的函数都可以始终转换为

    形式
        f :: a1 -> ... -> an -> m b
    

    然而,反过来是不可能的(一般而言)。

    我认为没有广泛使用术语'经典'和'松散'的monadic函数。

答案 2 :(得分:0)

对此的一个简短且(我希望)简单的答案是,一元函数的返回数据签名/类型与其输入数据签名/类型相同。

想象加号运算符的功能:

def plus(a,b):
    return a+b

这不是 monadic,因为它需要一个元组,而是返回一个值。

但改写为:

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 测试的原因,但欢迎对此的建议。

实际的最终结果应该是您能够将这些调用的整个集合串在一起,并提交它们的执行以多种方式执行 - 串行、分布式等,批量或按顺序针对数据集,并保持始终返回相同结果的信心。