"추상 오버"는 무엇을 의미합니까?
종종 Scala 문헌에서 "abstract over"라는 문구를 접하지만 의도를 이해하지 못합니다. 예를 들어 Martin Odersky는 다음과 같이 씁니다.
메서드 (또는 "함수")를 매개 변수로 전달하거나 추상화 할 수 있습니다. 유형을 매개 변수로 지정하거나 그 위에 추상화 할 수 있습니다.
또 다른 예로, "관찰자 패턴 사용 중단" 문서에서
이벤트 스트림이 일류 값인 결과는 그것들을 추상화 할 수 있다는 것입니다.
필자는 1 차 제네릭 "추상 형식"을 읽은 반면 모나드는 "형식 생성자에 대한 추상"을 읽었습니다. 그리고 우리는 또한 Cake Pattern 논문 에서 이와 같은 문구를 볼 수 있습니다 . 이러한 많은 예 중 하나를 인용하려면 :
추상 유형 멤버는 구체적인 유형의 구성 요소 를 추상화 하는 유연한 방법을 제공 합니다.
관련 스택 오버플로 질문도이 용어를 사용합니다. "매개 변수화 된 유형에 대해 실존 적으로 추상화 할 수 없습니다 ..."
그래서 .. "추상 오버"는 실제로 무엇을 의미합니까?
대수학에서 일상적인 개념 형성에서와 마찬가지로 추상화는 몇 가지 필수 특성으로 사물을 그룹화하고 특정 다른 특성을 생략하여 형성됩니다. 추상화는 유사성을 나타내는 단일 기호 또는 단어로 통합됩니다. 우리 는 차이점 을 추상화 한다고 말하지만 이것은 실제로 우리가 유사점으로 통합 된다는 것을 의미 합니다.
예를 들어, 숫자의 합을 취하는 프로그램을 고려 1
, 2
및 3
:
val sumOfOneTwoThree = 1 + 2 + 3
이 프로그램은 매우 추상적이지 않기 때문에 그다지 흥미롭지 않습니다. 모든 숫자 목록을 단일 기호 아래 통합하여 합산하는 숫자를 추상화 할 수 있습니다 ns
.
def sumOf(ns: List[Int]) = ns.foldLeft(0)(_ + _)
그리고 우리는 그것이 List라는 것도 특별히 신경 쓰지 않습니다. List는 특정 유형 생성자 (유형을 취하고 유형을 반환)이지만 원하는 필수 특성 (접을 수 있음)을 지정하여 유형 생성자를 추상화 할 수 있습니다.
trait Foldable[F[_]] {
def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
}
def sumOf[F[_]](ns: F[Int])(implicit ff: Foldable[F]) =
ff.foldl(ns, 0, (x: Int, y: Int) => x + y)
그리고 우리는 우리가 접을 수있는 모든 것에 Foldable
대한 암시 적 인스턴스를 가질 List
수 있습니다.
implicit val listFoldable = new Foldable[List] {
def foldl[A, B](as: List[A], z: B, f: (B, A) => B) = as.foldLeft(z)(f)
}
val sumOfOneTwoThree = sumOf(List(1,2,3))
또한 연산과 피연산자의 유형을 모두 추상화 할 수 있습니다 .
trait Monoid[M] {
def zero: M
def add(m1: M, m2: M): M
}
trait Foldable[F[_]] {
def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
def foldMap[A, B](as: F[A], f: A => B)(implicit m: Monoid[B]): B =
foldl(as, m.zero, (b: B, a: A) => m.add(b, f(a)))
}
def mapReduce[F[_], A, B](as: F[A], f: A => B)
(implicit ff: Foldable[F], m: Monoid[B]) =
ff.foldMap(as, f)
이제 우리는 꽤 일반적인 것을 가지고 있습니다. 이 방법 mapReduce
은 접을 수 있고 모노 이드이거나 하나로 매핑 될 F[A]
수 있음을 증명할 수 있는 모든 것을 F
접을 A
것입니다. 예를 들면 :
case class Sum(value: Int)
case class Product(value: Int)
implicit val sumMonoid = new Monoid[Sum] {
def zero = Sum(0)
def add(a: Sum, b: Sum) = Sum(a.value + b.value)
}
implicit val productMonoid = new Monoid[Product] {
def zero = Product(1)
def add(a: Product, b: Product) = Product(a.value * b.value)
}
val sumOf123 = mapReduce(List(1,2,3), Sum)
val productOf456 = mapReduce(List(4,5,6), Product)
우리는 모노 이드와 폴더 블 을 추상화했습니다 .
To a first approximation, being able to "abstract over" something means that instead of using that something directly, you can make a parameter of it, or otherwise use it "anonymously".
Scala allows you to abstract over types, by allowing classes, methods, and values to have type parameters, and values to have abstract (or anonymous) types.
Scala allows you to abstract over actions, by allowing methods to have function parameters.
Scala allows you to abstract over features, by allowing types to be defined structurally.
Scala allows you to abstract over type parameters, by allowing higher-order type parameters.
Scala allows you to abstract over data access patterns, by allowing you to create extractors.
Scala allows you to abstract over "things that can be used as something else", by allowing implicit conversions as parameters. Haskell does similarly with type classes.
Scala doesn't (yet) allow you to abstract over classes. You can't pass a class to something, and then use that class to create new objects. Other languages do allow abstraction over classes.
("Monads abstract over type constructors" is only true in a very restrictive way. Don't get hung up on it until you have your "Aha! I understand monads!!" moment.)
The ability to abstract over some aspect of computation is basically what allows code reuse, and enables the creation of libraries of functionality. Scala allows many more sorts of things to be abstracted over than more mainstream languages, and libraries in Scala can be correspondingly more powerful.
An abstraction is a sort of generalization.
http://en.wikipedia.org/wiki/Abstraction
Not only in Scala but many languages there is a need to have such mechanisms to reduce complexity(or at least create a hierarchy that partitions information into easier to understand pieces).
A class is an abstraction over a simple data type. It is sort of like a basic type but actually generalizes them. So a class is more than a simple data type but has many things in common with it.
When he says "abstracting over" he means the process by which you generalize. So if you are abstracting over methods as parameters you are generalizing the process of doing that. e.g., instead of passing methods to functions you might create some type of generalized way to handle it(such as not passing methods at all but building up a special system to deal with it).
In this case he specifically means the process of abstracting a problem and creating a oop like solution to the problem. C has very little ability to abstract(you can do it but it gets messy real quick and the language doesn't directly support it). If you wrote it in C++ you could use oop concepts to reduce the complexity of the problem(well, it's the same complexity but the conceptualization is generally easier(at least once you learn to think in terms of abstractions)).
e.g., If I needed a special data type that was like an int but, lets say restricted I could abstract over it by creating a new type that could be used like an int but had those properties I needed. The process I would use to do such a thing would be called an "abstracting".
Here is my narrow show and tell interpretation. It's self-explanatory and runs in the REPL.
class Parameterized[T] { // type as a parameter
def call(func: (Int) => Int) = func(1) // function as a parameter
def use(l: Long) { println(l) } // value as a parameter
}
val p = new Parameterized[String] // pass type String as a parameter
p.call((i:Int) => i + 1) // pass function increment as a parameter
p.use(1L) // pass value 1L as a parameter
abstract class Abstracted {
type T // abstract over a type
def call(i: Int): Int // abstract over a function
val l: Long // abstract over value
def use() { println(l) }
}
class Concrete extends Abstracted {
type T = String // specialize type as String
def call(i:Int): Int = i + 1 // specialize function as increment function
val l = 1L // specialize value as 1L
}
val a: Abstracted = new Concrete
a.call(1)
a.use()
The other answers give already a good idea of what kinds of abstractions exist. Lets go over the quotes one by one, and provide an example:
You can pass methods (or "functions") as parameters, or you can abstract over them. You can specify types as parameters, or you can abstract over them.
Pass function as a parameter: List(1,-2,3).map(math.abs(x))
Clearly abs
is passed as parameter here. map
itself abstracts over a function that does a certain specialiced thing with each list element. val list = List[String]()
specifies a type paramter (String). You could write a collection type which uses abstract type members instead: val buffer = Buffer{ type Elem=String }
. One difference is that you have to write def f(lis:List[String])...
but def f(buffer:Buffer)...
, so the element type is kind of "hidden" in the second method.
A consequence from our event streams being first-class values is that we can abstract over them.
In Swing an event just "happens" out of the blue, and you have to deal with it here and now. Event streams allow you to do all the plumbing an wiring in a more declarative way. E.g. when you want to change the responsible listener in Swing, you have to unregister the old and to register the new one, and to know all the gory details (e.g. threading issues). With event streams, the source of the events becomes a thing you can simply pass around, making it not very different from a byte or char stream, hence a more "abstract" concept.
Abstract type members provide flexible way to abstract over concrete types of components.
The Buffer class above is already an example for this.
Answers above provide an excellent explanation, but to summarize it in a single sentence, I would say:
Abstracting over something is the very same as neglecting it where irrelevant.
참고URL : https://stackoverflow.com/questions/4765532/what-does-abstract-over-mean
'IT story' 카테고리의 다른 글
Bash 스크립트 : #! / bin / bash는 무엇을 의미합니까? (0) | 2020.09.03 |
---|---|
HTML 요소에 JavaScript 객체를 첨부하는 좋은 방법이 있습니까? (0) | 2020.09.03 |
MVC 3 파일 업로드 및 모델 바인딩 (0) | 2020.09.03 |
"\ n"또는 '\ n'또는 std :: endl에서 std :: cout으로? (0) | 2020.09.03 |
JavaScript 이외의 다른 언어가 중괄호 시작 위치 (같은 줄과 다음 줄)에 차이가 있습니까? (0) | 2020.09.03 |