Haskell 单子';红管';和类型不同?

Haskell 单子';红管';和类型不同?,haskell,monads,Haskell,Monads,我说的是monad,“pipes”和“red pipe”。从表面上看,函数参数或类都是管道的类型,以确保一切都适合。然后它就变成了一个红色的烟斗,必须永远是一个红色的烟斗和纯净。这部分我不明白 为什么“红管”不能变成“蓝管”?可以将红色管道转换为普通管道吗?这和纯度有什么关系?我能想象这是类似于类RedPipe:PlainPipe{/*相同的接口和实现*/}?作者使用术语“红管”和“蓝管”作为隐喻。据我所知,这不是广泛使用的术语。我认为他的文章的关键点是,Java等语言提供的类型安全性有助于捕获

我说的是monad,“pipes”和“red pipe”。从表面上看,函数参数或类都是管道的类型,以确保一切都适合。然后它就变成了一个红色的烟斗,必须永远是一个红色的烟斗和纯净。这部分我不明白


为什么“红管”不能变成“蓝管”?可以将红色管道转换为普通管道吗?这和纯度有什么关系?我能想象这是类似于
类RedPipe:PlainPipe{/*相同的接口和实现*/}

作者使用术语“红管”和“蓝管”作为隐喻。据我所知,这不是广泛使用的术语。我认为他的文章的关键点是,Java等语言提供的类型安全性有助于捕获某些类型的程序员错误,将纯函数与非纯函数分离可以捕获更多错误。用他的一个例子:

square :: Double -> Double
这种类型的签名告诉我

  • 功能
    square
    没有任何副作用。它不会偷偷摸摸地更新数据库,也不会在屏幕上打印一些东西,也不会更改一些状态数据,否则会让我大吃一惊。(例如,在Java或C中,我必须阅读函数及其调用的任何函数,或者依赖文档来了解函数的功能。)

  • 每次我用一个特定的值调用它,比如说,
    square 5
    ,我都会得到完全相同的结果。这称为引用透明度,它允许编译器进行一些优化,因为它知道这个值永远不会改变,所以只需要计算一次


  • 作者使用“红管”和“蓝管”作为隐喻。据我所知,这不是广泛使用的术语。我认为他的文章的关键点是,Java等语言提供的类型安全性有助于捕获某些类型的程序员错误,将纯函数与非纯函数分离可以捕获更多错误。用他的一个例子:

    square :: Double -> Double
    
    这种类型的签名告诉我

  • 功能
    square
    没有任何副作用。它不会偷偷摸摸地更新数据库,也不会在屏幕上打印一些东西,也不会更改一些状态数据,否则会让我大吃一惊。(例如,在Java或C中,我必须阅读函数及其调用的任何函数,或者依赖文档来了解函数的功能。)

  • 每次我用一个特定的值调用它,比如说,
    square 5
    ,我都会得到完全相同的结果。这称为引用透明度,它允许编译器进行一些优化,因为它知道这个值永远不会改变,所以只需要计算一次


  • 在Haskell中,函数的类型确切地告诉您它做什么,更重要的是,它不做什么。这使得对Haskell代码进行推理变得更容易

    例如,如果我有以下类型的函数:

    f :: Int -> Int
    
    我知道它以一个
    Int
    作为输入,并生成一个
    Int
    作为输出,而它不做其他任何事情。重要的是,我知道它没有副作用

    如果我有一个类型为的函数:

    g :: Double -> State Int Double
    
    h :: Int -> Maybe String
    
    i :: String -> IO ()
    
    。。。该函数将一个
    Double
    作为参数,并生成一种生成
    Double
    的方法,但前提是我允许它查询或修改一些
    Int
    状态

    如果我有一个类型为的函数:

    g :: Double -> State Int Double
    
    h :: Int -> Maybe String
    
    i :: String -> IO ()
    
    我知道这个函数接受一个
    Int
    ,可能会生成一个
    字符串
    ,或者它可能会失败,什么也不产生。请注意,前两个函数都没有返回
    可能
    ,这意味着它们不能失败。默认情况下,Haskell不允许出现故障(即可为空的值)

    如果我有一个类型为的函数:

    g :: Double -> State Int Double
    
    h :: Int -> Maybe String
    
    i :: String -> IO ()
    
    我知道这个函数需要一个
    字符串
    ,可以运行来产生副作用。请注意,以前的函数都没有类型为
    IO
    ,这意味着它们不会产生副作用。默认情况下,Haskell不允许出现副作用。您必须在类型中显式地选择它们

    这意味着我们可以查看函数或值的类型,并立即了解它们使用的功能。例如,如果我在类型中看到一个
    Maybe
    ,我知道有失败的可能性,如果我没有,那么我知道没有失败的可能性。类似地,如果我在类型中看到
    IO
    ,那么我知道有潜在的副作用,但是如果我在类型中没有看到
    IO
    ,那么就没有潜在的副作用

    在主流语言中,您不具备选择性地“选择加入”功能的能力。默认情况下,所有功能始终处于启用状态,这意味着您必须始终检查
    null
    ,因为您无法保证某些功能没有失败,您必须始终运行测试,因为您无法保证某些功能没有隐式修改系统状态


    Haskell允许您限制函数的行为,以便对其“权限”进行更细粒度的控制,从而更容易扩展到没有bug的大型程序,也更容易阅读和理解Haskell代码,因为类型枚举了代码的全部行为,因此,您永远不必了解比类型允许的更多的内容。

    在Haskell中,函数的类型确切地告诉您它做什么,更重要的是,它不做什么。这使得对Haskell代码进行推理变得更容易

    例如,如果我有以下类型的函数:

    f :: Int -> Int
    
    我知道它以一个
    Int
    作为输入,并生成一个
    Int
    作为输出,而它不做其他任何事情。重要的是,我知道它没有副作用

    如果我有一个类型为的函数:

    g :: Double -> State Int Double
    
    h :: Int -> Maybe String
    
    i :: String -> IO ()
    
    。。。该函数将
    Double
    作为参数,并生成生成
    Double
    的方法,但前提是我允许它查询或修改一些
    Int