Как отобразить результаты OK

Я играю с примерами Elm и заметил, что пример field дает Result типов. После застревания я придумал этот упрощенный случай:

import Html exposing (text)
import String

f: Int -> Int
f x = x + 1

g: Result String Int -> Result String Int
g x = (Result.map f) x

main =
  text (  toString ( g  (String.toInt 5 ) ))

В результате отображается OK 6, и я бы предпочел, чтобы он отображал просто 6 -- я знаю, что toString принимает любой тип и возвращает его строковое представление. Так что, возможно, я могу изменить toString

  • если результат OK, то я могу распечатать числовой результат
  • если результат Err, то я хотел бы сделать какое-то пользовательское сообщение об ошибке

Возможно, это причина для andThen так как операция + 1 может завершиться неудачно.

andThen : Result e a -> (a -> Result e b) -> Result e b
andThen result callback =
    case result of
      Ok value -> callback value
      Err msg -> Err msg

Определение andThen — это именно то, что оно делает... и является экземпляром case.

Либо с andThen, либо со старым case, как мне исправить мой пример? Даже если я исправлю это сам, это может быть не самое похожее на Elm решение с хорошей обработкой ошибок. Поэтому публикую вопрос.


person john mangual    schedule 24.01.2016    source источник


Ответы (1)


Когда функция возвращает результат, у вас есть выбор — вы также можете вернуть результат, и в этом случае вы можете вернуть Err (что-то) или Ok (что-то). Это передает ваши ошибки вызывающей функции, которая может решить, что делать. Другой способ: вы можете вернуть что-то, что не является результатом, например String или Html. Если вы пойдете по этому второму пути, вам нужно обработать обе возможности Result и все еще вернуть вашу строку или HTML.

Так, например, эта функция принимает результат и возвращает строку. Он обрабатывает обе возможности, возвращая строку, даже если результат был Err.

foo: Result String Err -> String
foo myres = 
  case myres of 
    Ok(str) -> str
    Err(e) -> "there was an error! uh oh"

Это своего рода вопрос о том, как далеко вы хотите подняться по иерархии со своим Результатом. Вы хотите, чтобы ошибки просачивались на самый верхний уровень? Возможно, ваша функция верхнего уровня выглядит так:

View: Model -> Html
View model = 
  case makeMyHtml(model) of 
    Ok(htm) -> htm
    Err(e) -> renderSpecialErrorHtmlPage(e)

В любом случае, чтобы избавиться от «ОК» в этом случае, вы можете сделать это:

main =
  let res = g  (String.toInt 5 ) 
  text (  toString ( Result.withDefault "g returned an error!" res)) 

Если g вернет Ok(6), вы получите «6», но если он вернет ошибку, вы получите «g вернул ошибку!».

person Bzzt    schedule 24.01.2016