Infix operator với Type trong Scala

1306
13-05-2026
Infix operator với Type trong Scala

Tìm hiểu Infix operator với Type trong Scala, cách viết infix notation cho method và type, ví dụ dễ hiểu và lưu ý khi dùng trong Scala 2, Scala 3.

Infix operator với Type trong Scala

Trong Scala, infix notation thường được biết đến khi gọi method theo dạng tự nhiên hơn, thay vì luôn dùng dấu chấm và dấu ngoặc như các ngôn ngữ lập trình quen thuộc. Tuy nhiên, điểm thú vị là cách viết này không chỉ áp dụng cho method, mà còn có thể dùng trong Type Programming. Vậy Infix operator với Type trong Scala hoạt động như thế nào và khi nào nên sử dụng?

Infix notation trong Scala là gì?

Infix notation là cách viết một phép toán hoặc một method theo dạng đặt toán tử ở giữa hai thành phần. Nói đơn giản hơn, thay vì gọi method theo cú pháp thông thường bằng dấu chấm, Scala cho phép bạn viết theo kiểu gần giống ngôn ngữ tự nhiên hơn.

Ví dụ, với một method trong Scala:

object Foo {

def bar(s: String) = println(s)

}

Thông thường, bạn có thể gọi method như sau:

Foo.bar("hello")

Nhưng Scala cũng cho phép viết theo kiểu infix:

Foo bar "hello"

Hai cách viết trên về cơ bản cùng gọi đến method bar của object Foo. Điểm khác biệt chủ yếu nằm ở cách trình bày cú pháp.

Trong Scala 3, cú pháp infix vẫn được hỗ trợ, nhưng có một số quy tắc chặt chẽ hơn so với Scala 2. Với các method có tên dạng ký hiệu như +, ::, ->, infix vẫn là cách viết tự nhiên. Còn với method có tên chữ như bar, combine, append, Scala 3 khuyến khích khai báo rõ bằng từ khóa infix nếu muốn dùng theo dạng infix để code dễ đọc và nhất quán hơn.

Infix operator với Type trong Scala

Với cùng một cách suy nghĩ như khi gọi method, Scala cũng cho phép dùng infix notation ở cấp độ type. Đây là phần dễ gây khó hiểu với những ai mới tiếp cận Type Programming, nhưng nếu nhìn từ từ thì logic của nó khá đơn giản.

Giả sử có một trait nhận hai type parameter:

trait Foo[A, B]

Thông thường, khi tạo một type alias, bạn sẽ viết:

type Test1 = Foo[Int, String]

Nhưng Scala cũng cho phép viết theo dạng infix:

type Test2 = Int Foo String

Hai cách viết này có thể được hiểu tương đương nhau:

Foo[Int, String]

Int Foo String

Nói cách khác, trong Type Programming, Foo không chỉ được nhìn như một type constructor thông thường, mà còn có thể được xem như một “phép toán” giữa hai type.

Vì sao cách viết này dễ gây khó hiểu?

Nếu mới học Scala, bạn thường quen với cách viết:

List[String]

Option[Int]

Either[String, Int]

Đây là cách viết type theo dạng quen thuộc: tên type đứng trước, các type parameter nằm trong dấu ngoặc vuông.

Nhưng với infix type, cấu trúc lại được viết theo dạng:

A Foo B

Thay vì:

Foo[A, B]

Vì vậy, khi nhìn lần đầu, nhiều người có thể cảm thấy khó hiểu hoặc nghĩ rằng đây là một cú pháp đặc biệt nào đó. Thực tế, đây chỉ là một cách viết khác của type constructor có hai tham số.

Có thể hiểu đơn giản như sau:

Int Foo String

Tương đương với:

Foo[Int, String]

Tức là Foo nhận Int làm type thứ nhất và String làm type thứ hai.

Khi nào infix type trở nên hữu ích?

Infix type chỉ thực sự có ý nghĩa khi type đó mang tính biểu đạt cao, đặc biệt là trong các thư viện hoặc DSL cần cú pháp ngắn gọn, dễ đọc.

Một ví dụ quen thuộc trong hệ sinh thái Scala là kiểu ::, thường gợi liên tưởng đến thao tác nối hoặc xây dựng danh sách type-level.

Ví dụ:

trait ::[A, B]

Nếu viết theo cách thông thường:

type Test3 = ::[Int, String]

Cách viết này đúng, nhưng nhìn chưa thật sự tự nhiên.

Trong khi đó, nếu viết theo infix notation:

type Test4 = Int :: String

Cách viết này trực quan hơn, vì :: nằm giữa hai type và thể hiện rõ hơn ý nghĩa “kết nối” hoặc “ghép” giữa Int String.

Đây là lý do infix type thường xuất hiện trong các thư viện thiên về type-level programming, generic programming hoặc DSL, nơi cú pháp cần ngắn gọn và giàu tính biểu đạt.

So sánh cách viết thông thường và cách viết infix

Cách viết thông thường

Cách viết infix

Ý nghĩa

Foo[Int, String]

Int Foo String

Foo nhận hai type parameter là Int String

::[Int, String]

Int :: String

:: được dùng như một toán tử ở cấp độ type

Map[String, Int]

Không thường dùng dạng infix

Một số type không nên ép viết infix nếu không giúp code dễ hiểu hơn

Điểm quan trọng ở đây là không phải type nào cũng nên viết theo dạng infix. Nếu cách viết infix làm code khó đọc hơn, bạn nên ưu tiên cách viết truyền thống bằng dấu ngoặc vuông.

Lưu ý khi dùng infix type trong Scala 3

Trong 2026, cần lưu ý rằng Scala 3 có xu hướng làm cú pháp rõ ràng và nhất quán hơn. Một số cú pháp từng phổ biến trong Scala 2 vẫn được hỗ trợ ở mức độ nhất định, nhưng có thể phát sinh cảnh báo hoặc không còn được khuyến khích trong các trường hợp cụ thể.

Với infix notation, Scala 3 phân biệt rõ hơn giữa operator dạng ký hiệu và operator dạng chữ. Các operator dạng ký hiệu như +, ::, -> thường vẫn phù hợp với infix notation. Trong khi đó, các tên dạng chữ nên được dùng cẩn thận, hoặc khai báo bằng infix nếu thiết kế API có chủ đích cho cách viết này.

Vì vậy, khi viết code Scala hiện đại, bạn nên ưu tiên các nguyên tắc sau:

Trường hợp

Khuyến nghị

Type có tên ký hiệu, ví dụ ::, `

, ~>`

Type có tên chữ, ví dụ Foo, Result, Pair

Chỉ nên dùng infix nếu thật sự có ý nghĩa biểu đạt

Code cho người mới học Scala

Nên ưu tiên cú pháp thông thường để dễ hiểu

Code thư viện hoặc DSL

Có thể dùng infix để tạo cú pháp tự nhiên hơn

Có nên dùng infix operator với Type trong Scala không?

Câu trả lời là có, nhưng nên dùng có chọn lọc.

Infix type giúp code ngắn gọn và biểu đạt tốt hơn trong một số ngữ cảnh, đặc biệt khi bạn đang làm việc với type-level programming, generic programming hoặc xây dựng DSL. Tuy nhiên, nếu lạm dụng, cú pháp này có thể khiến code khó đọc, nhất là với những người chưa quen với Scala.

Ví dụ, cách viết sau có thể hợp lý nếu :: mang ý nghĩa rõ ràng:

type Result = Int :: String

Nhưng với một type có tên thông thường như Foo, cách viết này:

type Result = Int Foo String

Có thể khiến người đọc bối rối nếu họ chưa biết Foo là một type constructor nhận hai tham số.

Trong thực tế, nếu mục tiêu là dễ hiểu, bạn có thể viết rõ ràng hơn:

type Result = Foo[Int, String]

Còn nếu mục tiêu là tạo DSL hoặc biểu diễn type theo cách tự nhiên hơn, infix type sẽ là một lựa chọn đáng cân nhắc.

Kết luận

Infix operator với Type trong Scala là một cú pháp thú vị, cho phép viết type constructor hai tham số theo dạng tự nhiên hơn, ví dụ Int Foo String thay cho Foo[Int, String]. Cách viết này đặc biệt hữu ích trong Type Programming hoặc DSL, nơi type không chỉ đóng vai trò khai báo dữ liệu mà còn thể hiện quan hệ giữa các kiểu. Tuy nhiên, với Scala hiện đại, đặc biệt là Scala 3, bạn nên dùng infix notation có chủ đích để đảm bảo code vừa ngắn gọn, vừa dễ đọc và dễ bảo trì.

Xem thêm: Ba cách căn bản để chạy chương trình Scala

TAGS: scala
SHARE
Zalo