如何从纯函数调用不纯函数? [英] How to call impure functions from pure ones?

查看:83
本文介绍了如何从纯函数调用不纯函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚读完一本学到Haskell来成就伟大的事物!".书,所以我的问题可能很幼稚. 我不明白的是如何从纯代码中调用不纯"的IO函数.

I have just finished reading a "Learn You a Haskell for Great Good!" book so my question can be very naive. What I don't understand is how to call "impure" IO functions from the pure code.

这是一个用C#编写的工作示例.在我们的业务逻辑中,我们根据天气计划一些行动.我们以通常的C#方式进行操作.

Here is a working example written in C#. In our business logic we plan some actions based on weather. We do it in usual C# manner.

interface IWeatherForecast
{
    WeatherData GetWeather(Location location, DateTime timestamp);
}

// concrete implementation reading weather from DB
class DbWeather : IWeatherForecast
{
    public override WeatherData GetWeather(Location location, DateTime timestamp)
    {...}
}

class WeatherFactory
{
    public IWeatherForecast GetWeatherProvider()
    {...}
}

// Business logic independent from any DB
class MaritimeRoutePlanner
{
    private IWeatherForecast weatherProvider = weatherFactory.GetWeatherProvider();

    public bool ShouldAvoidLocation(Location location, DateTime timestamp)
    {
        WeatherData weather = weatherProvider.GetWeather(location, timestamp);
        if(weather.Beaufort > 8)
            return true;
        else...
            ...
    }
}

如何在Haskell中实现此逻辑?

How do I implement this logic in Haskell?

实际上,纯逻辑" MaritimeRoutePlanner调用了"c1",这是纯IO".

In reality "pure logical" MaritimeRoutePlanner calls weatherProvider.GetWeather() which is "impure IO" stuff.

在Haskell中可能吗?您将如何在Haskell中对此建模?

Is it possible in Haskell? How would you model this in Haskell?

推荐答案

常见问题(如何从纯函数调用不纯函数)是一个常见问题.参见例如这个问题及其答案:如何从不纯方法中返回纯值

The general question (how to call an impure function from a pure function) is a FAQ. See e.g. this question and its answers: How to return a pure value from a impure method

与其他与软件体系结构相关的主题一样,如何以更具功能性的方式构造代码也取决于环境.您正在编写哪种程序? REST API?智能手机应用程序?控制台程序?批处理工作?加载项?

How you structure code in a more functional manner depends, like any other topic related to software architecture, on circumstances. What sort of program are you writing? A REST API? A smartphone app? A console program? A batch job? An add-in?

在许多情况下,您可以摆脱所谓的不纯-纯-不纯三明治:

In many cases, you can get away with what I call an impure-pure-impure sandwich:

  1. 从不纯来源收集所有必需的数据
  2. 使用该数据调用纯函数
  3. 对纯函数的返回值做一些不纯的事情

在Haskell中,您可以执行此操作,因为切入点始终是不纯的.这是天气决策问题的简单示意图.首先定义要使用的数据.在这里,我仅包含beaufort值,但我假设WeatherData将包含更多数据(这就是为什么我将其定义为data而不是newtype的原因).

In Haskell you can do this because entry points are always impure. Here's a simple sketch of the weather decision problem. You start by defining the data on which you'll work. Here, I only include the beaufort value, but I assume that WeatherData would include more data than that (which is why I define it as data and not as a newtype).

data WeatherData = WeatherData { beaufort :: Int } deriving (Eq, Show)

您现在可以将决策逻辑编写为纯函数:

You can now write the decision logic as a pure function:

shouldAvoidLocation :: WeatherData -> Bool
shouldAvoidLocation weather = beaufort weather > 8

加载数据是一个完全具体的操作:

Loading data is an entirely concrete operation:

readWeatherFromDb :: Location -> LocalTime -> IO WeatherData
readWeatherFromDb location timestamp = -- implementation goes here...

这里没有明确的抽象.该函数读取数据并返回不纯数据.这可能是不纯-纯-不纯三明治中的第一步(不纯).

There's no explicit abstraction in place here. This function reads data and returns impure data. That could be the first (impure) step in the impure-pure-impure sandwich.

现在可以根据该体系结构来构造应用程序的入口点:

The entry point of the application can now be structured according to that architecture:

main :: IO ()
main = do
  w <- readWeatherFromDb Berlin $ LocalTime (fromGregorian 2019 8 29) (TimeOfDay 8 55 8)
  if shouldAvoidLocation w
    then putStrLn "Avoid"
    else putStrLn "Go"

shouldAvoidLocation的调用是三明治中间的好东西,然后是不纯的putStrLn调用.

The call to shouldAvoidLocation is the good, pure stuff in the middle of the sandwich, which is then followed by impure putStrLn calls.

这篇关于如何从纯函数调用不纯函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆