2017-11-24 6 views
1

私は関数型プログラミングとKotlinの絶対初心者です。私は自分自身に質問している質問から作成した演習を解決しようとしています。私の現在の質問"ポートとアダプタのアーキテクチャを使って実際のアプリケーションに実際の機能プログラミングをする方法は?"Kotlinいずれかのモナド:CPSを処理するためのコンストラクタコールをリファクタリングする

現在Eitherモナドについて学び、私はPerhaps<T>exception handlingで使用するだけで、名前を変更Either<Err, T>である以下の機能を持っています。

この関数は、任意のHTTPパラメータを含むRequestModelを取ります。Perhapsは、LocalDateを含むデータクラスのを返します。オブジェクト指向言語で

private fun requestCountBetweenQueryA(model: RequestModel): Perhaps<CountBetweenQuery> { 
    return try { 
     Perhaps.ret(CountBetweenQuery(extractLocalDateOrThrow(model, "begin"), extractLocalDateOrThrow(model, "end"))) 

    } catch (e: UnsupportedTemporalTypeException) { 
     Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID) 

    } catch (e: DateTimeException) { 
     Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID) 
    } 
} 

private fun extractLocalDateOrThrow(it: RequestModel, param: String): LocalDate = 
     LocalDate.from(DateTimeFormatter.ISO_DATE.parse(it.parameters.first { it.key == param }.value)) 

その例外が(重複コードを単一のメソッドに抽出される)上記共通の例外ハンドラのいずれかの方法以下の取り扱い、またはより高いので、私はこれをリファクタリングであろう。当然のことながら、私は私の運動の一環としてperhapsExtractLocalDateに私extractLocalDateOrThrowを有効にする:

private fun perhapsExtractLocalDate(it: RequestModel, param: String): Perhaps<LocalDate> = try { 
    Perhaps.ret(LocalDate.from(DateTimeFormatter.ISO_DATE.parse(it.parameters.first { it.key == param }.value))) 

} catch (e: UnsupportedTemporalTypeException) { 
    Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID) 

} catch (e: DateTimeException) { 
    Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID) 
} 

私は継続渡しスタイルを維持しながらCountBetweenQueryのコンストラクタを呼び出す方法を把握しようとしている時間のために苦労しています。最初は

private fun requestCountBetweenQueryB(me: RequestModel): Perhaps<CountBetweenQuery> { 
    val newCountBetweenQueryCurried: (begin: LocalDate) -> (end: LocalDate) -> CountBetweenQuery = 
      ::CountBetweenQuery.curried() 

    return Perhaps.ret(newCountBetweenQueryCurried) 
      .bind { function -> perhapsExtractLocalDate(me, "begin").map(function) } 
      .bind { function -> perhapsExtractLocalDate(me, "end").map(function) } 
} 

私は二つの方法がperhapsExtractLocalDateが独立している呼び出すためので、私は応用的なスタイルを使用し、returnapplyを使用することを期待していた:これは私が思い付いたものです

。代わりに私はbindの使用を避ける方法を理解することができませんでした。これは私の理解からですが、モナド様式を意味しています。

私の質問は以下のとおりです。私の理解が正しけれ

  • 場合、どのように私は応用的なスタイルにこれを回すことができますか?

  • 上記の実装で重大な間違いがありますか? (すなわち、イディオム、カレーの誤用)

答えて

1

私は何が間違っていたのか分かったと思います。

適切な関数型プログラミング言語で書かれたFPの例では、アプリケーションスタイルはsomeFunction map a apply bのように書かれていますが、Kotlinではオブジェクトのメソッドを扱っているため、これは左から右へ読むときは予約注文引数評価の点で正しい順序。これは私を非常に混乱させた。

private fun requestCountBetweenQueryC(me: RequestModel): Perhaps<CountBetweenQuery> { 
    val newCountBetweenQueryCurried: (begin: LocalDate) -> (end: LocalDate) -> CountBetweenQuery = 
      ::CountBetweenQuery.curried() 

    val a = perhapsExtractLocalDate(me, "begin") 
    val b = perhapsExtractLocalDate(me, "end") 

    return b.apply(a.map(newCountBetweenQueryCurried)) 
} 

私の理解が正しい場合、これはlift2機能とも呼ばれます。

関連する問題