예외가 결과보다 덜(순수)합니까?

9864 단어 discussfunctional
최근에 Railway Oriented Programming에 대한 비디오를보고 스스로를 도울 수 없지만 "왜"라고 묻습니다. 그래서 같은 작가의 작품Against Railway-Oriented Programming을 검색해서 찾았습니다. 그래도 저는 이렇게 묻고 싶습니다. "내가 단순히 예외를 throw하고 이 모든 것을 무료로 가질 수 있는데 일치하지 않는 기능을 작성하는 방법을 가르쳐야 하는 이유는 무엇입니까? 그리고 이것은 이 비디오뿐만이 아닙니다. 최근 OOP 증오 및 기능 열정, 나는 함수가 순수하고 동일한 입력 데이터에 대해 항상 동일한 출력 데이터를 반환하기 때문에 어떻게하는지 항상 듣는다.그리고 나서 나는 질문이 온다.그것은 예외와 다른가?

내가 아는 바로는 동일한 인수에 대해 동일한 결과를 반환할 때 함수가 순수하다는 것입니다. 그리고 함수가 항상 동일한 입력 인수에 대해 동일한 예외를 throw하는 경우it is pure . 심지어 reducers in Redux 부작용이 없고 항상 예외가 발생하는 경우 순수한 것으로 간주됩니다(유명한 undefined는 객체/함수/...가 아닙니다). 그래서 다른 것이 있어야 합니다. 전체 철도에서 예외를 던지는 단순함을 포기하고 더 나은 접근 방식이라고 부르고 싶은 이유. 아래는 그것을 찾으려는 예입니다.

type Result = 
  | {success: true, processedData: ProcessedData}
  | {success: false, error: string};

/**
 * Pure function with the "Result" type.
 */
function pureFunction(user?: User, data: Data): Result {
  if (!user) {
    return {success: false, error: 'User is not authenticated'}
  }

  return {success: true, processedData: {...data, processed: true}}
}

/**
 * The same function but "returning" an error as an exception.
 */
function maybePureFunction(user?: User, data: Data): ProcessedData {
  if (!user) {
    return throw new UserNotAuthenticated(user)
  }

  return {...data, processed: true}
}


차이점을 알 수 있습니까? 저 할 수 있어요. 유형에 숨겨져 있습니다. 나는 예외 유형을 확인하는 언어를 모릅니다. Java는 어떻게 든 , Python don't plan it 을 시도했습니다. 아무도 모든 함수(죄송합니다, 메소드)에서 던질 수 있는 모든 예외를 작성하고 싶어하지 않습니다. 그래도 모든 반환 유형을 작성하는 것과 동일합니다. 따라서 이것은 Return 유형 - 유형 안전성의 큰 장점입니다. 컴파일러는 가능한 오류를 처리하지 않지만 잡히지 않은 예외에 대해 경고하지 않는다고 알려줍니다.

그리고는 다시 물어야 했다. 왜요? 왜 우리는 두 가지 장점을 모두 가질 수 없습니까? 예외를 던지고 컴파일러가 함수에 대한 예외를 유추하고 가능성에 대해 경고하도록 할 수 없는 이유는 무엇입니까? 그런 다음 bind , >>= 등으로 기능을 결합하는 방법을 배울 필요가 없습니다. Java에서 확인/확인되지 않은 예외의 아이디어가 좋다고 생각합니다. 나는 그것들의 이름을 BusinessExceptionProgrammerError 또는 이와 비슷한 이름으로 지정할 것입니다. 그리고 그것들은 컴파일러에 의해 추론될 것입니다.

사실, 나는 예외를 대수적 데이터 유형sum types 또는 enums as defined by Rust으로 간주하는 것을 두려워하지 않습니다. 여기 내 이상적인 API가 있습니다.

try {
    return maybePureFunction(user, data)
} catch (e) {
    // here the compiler knows "e" is "UserNotAuthenticated"
    return DATA_FOR_ANONYMOUS_USER
}

// OR

// compiler infers here the function return type is kind-of "Result<ResourceNotFound | DangerousError, string>"
function something(fileName: string): string {
    try {
        return dangerousCall(fileName)  // throws "DangerousError" unhandled here
    } catch (e: FileDoesNotExist | InsufficientPermissions) {
        throw new ResourceNotFound(fileName);
    } catch (e: FileLocked) {  // isn't this actually pattern matching?
        return ""
    }
}


당신이 그것에 대해 어떻게 생각하십니까? 그리고 더 중요한 것은 예외가 유형 시스템의 적절한 부분이고 함수의 결과로 처리되는 언어를 알고 있습니까?

흥미로운 소스


  • A pure function must have Referential Transparency
  • Why is catching an exception non-pure, but throwing an exception is pure?
  • https://stackoverflow.com/questions/10703232/why-is-the-raising-of-an-exception-a-side-effect

  • https://stackoverflow.com/questions/36597079/what-is-the-purpose-of-throwing-exceptions-in-pure-functions
  • https://www.reddit.com/r/scala/comments/a2odjb/can_a_pure_function_throw_exceptions/
  • https://www.reddit.com/r/haskell/comments/7wblve/exceptions_in_pure_functions/
  • http://lambda-the-ultimate.org/node/4544
  • https://blog.jooq.org/javas-checked-exceptions-are-just-weird-union-types/
  • https://itnext.io/my-personal-definitive-guide-to-java-exceptions-d2e4131393c7
  • 좋은 웹페이지 즐겨찾기