gpt4 book ai didi

function - 我为这些条件做些什么来遵循 FP?

转载 作者:行者123 更新时间:2023-12-01 07:37:53 27 4
gpt4 key购买 nike

我正在阅读 FP,我有两个基本问题:

  • FP 表示函数应该接受一个输入并给出单个输出。那么我该怎么办void方法?它不返回任何东西吗?
  • FP 说函数应该是单一的
    责任,那我们怎么处理log方法内的语句?这不违反规定?

  • 想知道他们如何在 Scala、Haskell 中处理这些事情。
    提前致谢。

    最佳答案

    我假设您正在阅读一本名为“函数式编程”的书,尽管这也有助于了解作者是谁。无论如何,这些问题相对容易回答,我将就 Haskell 给出我的答案,因为我不了解 Scala。

    So what should I do with void methods? It doesn't return anything right?



    没有 void像 Haskell 这样的纯函数式语言中的方法。纯函数没有副作用,所以没有返回值的纯函数是没有意义的,比如

    f :: Int -> ()
    f x = let y = x * x + 3 in ()

    不会做任何计算, y永远不会计算,您提供的所有输入都将返回相同的值。但是,如果您有一个不纯的函数,例如写入文件或将某些内容打印到屏幕的函数,那么它必须存在于 monadic 上下文中。如果您还不了解 monad,请不要担心。它们需要一点时间来习惯,但它们是一个非常强大和有用的抽象,可以使很多问题变得更容易。 monad 类似于 IO , 在 Haskell 中,这需要一个类型参数来指示可以存储在此上下文中的值。所以你可以有类似的东西

    putStrLn :: String -> IO ()

    或者

    -- FYI: FilePath is an alias for String
    writeFile :: FilePath -> String -> IO ()

    这些都有副作用,由 IO something 的返回值表示,以及 ()某事意味着该操作没有有意义的结果。例如,在 Python 3 中, print函数返回 None因为在将值打印到屏幕后没有任何有意义的返回。 ()也可以表示一元上下文具有有意义的值,例如在 readFile 中或 getLine :

    getLine :: IO String
    readFile :: FilePath -> IO String

    在写您的 main 时功能,你可以做类似的事情

    main = do
    putStrLn "Enter a filename:"
    fname <- getLine -- fname has type String
    writeFile fname "This text will be in a file"
    contents <- readFile fname
    putStrLn "I wrote the following text to the file:"
    putStrLn contents

    FP says function should have single resresponsibility, then how do we handle log statements inside the method? That doesn't violate the rule?



    大多数函数不需要在它们内部进行日志记录。我知道这听起来很奇怪,但这是真的。在 Haskell 和大多数其他函数式语言中,您将编写许多小的、易于测试的函数,每个函数只执行一个步骤。在您的应用程序中有很多 1 或 2 行函数是很常见的。

    当您确实需要进行日志记录时,假设您正在构建一个 Web 服务器,您可以采用几种不同的方法。实际上有一个名为 Writer 的 monad这使您可以在执行操作时聚合值。这些操作不必是不纯的和做 IO 的,它们可以是完全纯的。然而,一个可能用于 Web 服务器或大型应用程序的真正日志框架可能会带有自己的框架。这样您就可以设置对屏幕、文件、网络位置、电子邮件等的日志记录。这个 monad 将包裹 IO monad 以便它可以执行这些副作用。更高级的人可能会使用一些更高级的库,如 monad 转换器或可扩展效果。这些使您可以将不同的 monad 组合在一起,以便您可以同时使用两者的实用程序。你可能会看到这样的代码

    type MyApp a = LogT IO a

    -- log :: Monad m => LogLevel -> String -> LogT m ()

    getConnection :: Socket -> MyApp Connection
    getConnection sock = do
    log DEBUG "Waiting for next connection"
    conn <- liftIO $ acceptConnection sock
    log INFO $ "Accepted connection from IP: " ++ show (connectionIP conn)
    return conn

    我不希望你完全理解这段代码,但我希望你能看到它混合了日志和网络操作。 liftIO函数是 monad 转换器的常见功能,它将 IO 操作“转换”为包装 IO 的新 monad。

    这听起来可能很令人困惑,如果您习惯了 Python、Java 或 C++ 之类的语言,那么一开始可能会如此。我当然是!但是在我习惯了以这种不同的方式思考问题之后,我希望我一直都在 OOP 语言中拥有这些结构。

    关于function - 我为这些条件做些什么来遵循 FP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26363506/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com