2017-01-11 2 views
1

하스켈 용 일반 라이브러리를 스칼라로 이식하려고합니다. 그러나, 나는 현재 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 (일반)는 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)) 
} 

: 이것은 내가 일을하고 싶은 방법입니다 크러시 기능을 사용하려면

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

그래서 생각 해낸 해결책은 내가 호감이 기능에 대해 동일한를 사용할 수 있도록 더 많은 부분으로 분쇄 기능을 분할하는 것입니다 : 이것은 내가받은 오류입니다. 이것은 현재 솔루션을 컴파일된다 :

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) 
} 

지금 당신은 자신을 요청할 수 있습니다 : 모든 잘못 경우이 오류 메시지가 누락 된 점이다 그 이유는 무엇입니까? 음, scala는 중절 표기법을 지원합니다. 을 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]의 할 필요가있다.

솔직히 말해서 scalac이 무딘 코드를 구문 분석하여 프로세스의 괄호를 완전히 무시한 버그와 같은 것처럼 보입니다. 그림자 형식의 param의 경우 불행한 구문 변덕 :-)

+0

-Xlint라고합시다. ''hello '+ ("world"). 구문을 어떻게 해석할까요? 멤버 (연산자)가 섞여서 사용할 수있는 것을 나타 내기 위해 주석을 추가하려고한다고 생각합니다. 그것은 가독성을 높이기위한 것이지만, Abide 규칙은 공백 문자 (공백 문자 등)가 따르지 않는 alnum 삽입 문자에 대해 경고 할 수 있습니다. –

+0

당신 말이 맞아요. 그게 효과가있어! 훌륭한 설명에 감사드립니다! – maffh

관련 문제