2017-01-11 10 views
1

Haskell用の汎用ライブラリをScalaに移植しようとしています。しかし、私は現在、Scalaの一般的なCrush関数をどうやって解決したか、本当に満足していません。Scala後で定義される複数の型パラメータ

私はCrush関数を扱うために以下の扱いに定義しました。

trait FRep[G[_],F[_]]{ 
    def frep[A](g1 : G[A]) : G[F[A]] 
    } 

trait Crush[B,A]{ 
    def selCrush : Assoc => A => B => B 
} 

次に、クラッシュ関数を定義したかったが、ここで問題に遭遇した。問題は、Crush関数を表すためにこのFRep特性が必要ですが、frepのG(Generic)は1つのパラメータしか許さないということです。私はラムダ型を使ってこれを解決しましたが、まだ関数を定義するのにいくつかの問題があります。クラッシュ関数のパラメータが同じである必要が暗黙の担当者変数にラムダ式と同じではありませんので、これは明らかに、エラーを与えた

def crush[B,A,F[_]](asc : Assoc)(f : A => B => B)(z : B)(x : F[A])(implicit rep : FRep[({type AB[A] = Crush[B,A]})#AB,F]): B = { 
    def fCrush = new Crush[B,A]{ 
     override def selCrush= _ => f 
    } 
    return(rep frep(fCrush).selCrush(asc)(x)(z)) 
} 

:これは私が仕事したかったアプローチでありますCrush機能を使用するために使用します。

<pastie>:677: error: type mismatch; 
found : x.type (with underlying type F[A]) 
required: A 
     return(rep frep(fCrush).selCrush(asc)(x)(z)) 

だから、私が思いついた解決策は、私がクラッシュ機能のために同じAを使用することができ、そのようなことを、より多くの部分にクラッシュ機能を分割することです。これは私が受け取ったエラーです。これは現在コンパイルされているソリューションです:

class CrushFunction[B,F[_]](asc : Assoc)(z : B)(implicit rep : FRep[({type AB[A] = Crush[B,A]})#AB,F]){ 
    def crush[A](f : A => B => B)(x : F[A]) : B = { 
     val crushVal = new Crush[B,A]{ 
      override def selCrush: Assoc => A => B => B = _ => f 
     } 
     return(rep.frep(crushVal).selCrush(asc)(x)(z)) 
    } 
} 

私の質問です:これを解決するより良い方法はありますか?

答えて

2

実際に最初の解決策が間違っているのは、repfrepの間にドットを残していないことだけです。私は(A)にも明示的にreturnを使用しないように助言する、および型パラメータの名前をシャドウしない:

def crush[B,A,F[_]](asc : Assoc)(f : A => B => B)(z : B)(x : F[A])(implicit rep : FRep[({type AB[X] = Crush[B,X]})#AB,F]): B = { 
    def fCrush = new Crush[B,A]{ 
     override def selCrush: Assoc => A => B => B = _ => f 
    } 
    rep.frep(fCrush).selCrush(asc)(x)(z) 
} 

は今、あなたは自分自身に尋ねることがあります。すべてのことが間違っている場合は、このエラーメッセージが不足している点である理由?まあ、スカラは中置表記をサポートしています。 をa.b(c).d(e)として解析します。しかし、あなたは次のように書いた:a b(c).d(e)。これはパーサを混乱させます。 //printをREPL(私が考えるバージョン2.11.8以上)のコードに追加し、Tabキーを押すと何が起こるかを見ることができます。

私はあなたのためにすべての塊をろ過しました。 rep frep(fCrush).selCrush(asc)(x)(z)は以下のように解析されます:その発現x

rep.frep[A](fCrush.selCrush(asc)(x)(z)) 

実際タイプA代わりにF[A]であることが要求されます。

正直言って、スケーラックがスケーラブルなコードを解析して、プロセスのかっこを完全に無視してしまうバグのようです。 残念なことに文法を変えてみましょう:-)

+0

-Xlint(陰影付きタイプのparam)。あなたは '' hello '+( "world")をどのようにパースしますか?私は、メンバ(オペレータ)を静的に使用できることを示す注釈を追加したいと考えています。それは可読性を助けるためですが、おそらく、Abideルールは空白(空白)が続くことのないアルナムの中置について警告する可能性があります。 –

+0

あなたは正しいです。それは動作します!素晴らしい説明をありがとう! – maffh

関連する問題