2017-12-02 7 views
1

저는 최근에 고양이 라이브러리를 연구 중이며 NonEmptyList라는이 클래스를 보았습니다.cats 'NonEmptyList 대 scala stdlib ::

api를 읽은 후 고양이 작성자가 (: :) 내장 된 것을 활용하는 대신 새로운 클래스를 만들고 그것을 확장하기 위해 typeclasses를 사용하는 것이 무엇인지 궁금해 할 수 없었습니다. 고양이 github 페이지에도 열거되지 않았으므로 여기에 대해 물어 보았습니다. cons는 List의 하위 유형이므로 아마도 그럴 수 있습니까? (비록 그것의 의미를 모르겠다)

::와 NEL의 차이점은 무엇입니까? 그리고 왜 고양이 제작자는 :: 대신에 NEL을 써야 했습니까?

답변

3

List로부터 연장하지 않는 NonEmptyList을 갖는 주된 이유는 가정에서의 API를 포함 현상 경험이다.

먼저 ::에는 모든 방법이 있습니다. List은 오도 된 수 있으며 더 강력한 가정을 사용하여 더 나은 API를 설계하는 것을 어렵게 만듭니다. 또한 List에는 직접 ::을 반환하는 메서드가 없으므로 개발자는 비어 있지 않은 추상화를 수동으로 유지해야합니다.

제가 실제로 무엇을 의미하는지 보여주는 당신에게 예를 보여 드리죠 : NonEmptyListList, 즉 filter, filterNotcollect을 반환 방법을 가지고

// NonEmptyList usage is intuitive and types fit together nicely 
val nonEmpty: NonEmptyList[Int] = NonEmptyList.of(1, 2, 3) 
val biggerNonEmpty: NonEmptyList[Int] = 0 :: nonEmpty 
val nonEmptyMapped: NonEmptyList[Int] = nonEmpty.map(_ * 2) 

// :: has lots of problems 
// PROBLEM: we can't easily instantiate :: 
val cons: ::[Int] = 1 :: 2 :: 3 :: Nil // type mismatch; found: List[Int]; required: ::[Int] 
val cons: ::[Int] = new ::[Int](1, ::(2, ::(3, Nil))) 

// PROBLEM: adding new element to Cons returns List 
val biggerCons: ::[Int] = 0 :: cons // type mismatch; found: List[Int]; required: ::[Int] 

// PROBLEM: ::.map returns List 
val consMapped : ::[Int] = cons.map(_ * 2) // type mismatch; found: List[Int]; required: ::[Int] 

참고. 왜? NonEmptyList을 통한 필터링은 모든 요소를 ​​필터링하여 목록이 비어있을 수 있음을 의미 할 수 있습니다.

전체가 이 아닌 것입니다. 추상화가 너무 강력합니다. 함수 입력 및 출력 유형을 올바르게 사용하면 API에 대한 가정을 인코딩 할 수 있습니다. ::은 이러한 추상화를 제공하지 않습니다.