在Scala中实现类型类A和B的元素列表

时间:2016-09-09 23:23:49

标签: scala typeclass

在尝试在整个项目中使用类型类时,我遇到了以下问题。

trait FooAble[T] { def fa(t: T): List[T] }
object Foo { def apply[T](t: T) = implicitly[FooAble[T]].fa(t) }

trait BarAble[T] { def fb(t: T): Double }
object Bar { def apply[T](t: T) = implicitly[BarAble[T]].fb(t) }

并希望能够做到以下几点:

// xs contains elements of type A and B which are subclasses of the trait Something
def f(xs: List[Something]) = {
  val something = xs.map(Foo)
  val somethingElse = xs.map(Bar)
}

但是,这不起作用,因为我们不知道Something是否实现A[]B[],没有发现隐式实现。我需要做什么才能使列表xs的元素实现类型FooAbleBarAble

1 个答案:

答案 0 :(得分:0)

我认为这个问题:What are type classes in Scala useful for?将帮助您理解类型类的正确用法(和实用性)。

我只是在上面的链接中为你的用例扩展了Kevin Wright的答案(如果我理解你的需要正确!):

<link href="~/Content/jquery.jqGrid/ui.jqgrid.css" rel="stylesheet" />
<link href="~/Content/themes/base/jquery.ui.button.css" rel="stylesheet" />
<link href="~/Content/themes/base/jquery.ui.theme.css" rel="stylesheet" />
<script src="~/Scripts/i18n/grid.locale-en.js"></script>
<script src="~/Scripts/jquery.jqGrid.min.js"></script>



$("#gridViewEditable").jqGrid({
            data: data,
            datatype: "local",
            cmTemplate: { sortable: false },
            colNames: ['Actions', "QuotationDetailID", "QuotationID", "ServiceID", "ServiceDescription", "Unit", "Rate", "Discount", "Frequency", "FrequencyBase", "Total"],
            colModel: [
                ///
                {
                    name: 'Actions', index: 'Actions', width: 55, align: 'center', sortable: false, formatter: 'actions',
                    formatoptions: {
                        keys: true, // we want use [Enter] key to save the row and [Esc] to cancel editing.
                        onEdit: function (rowid) {
                            alert("in onEdit: rowid=" + rowid + "\nWe don't need return anything");
                        },
                        onSuccess: function (jqXHR) {
                            // the function will be used as "succesfunc" parameter of editRow function
                            // (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#editrow)
                            alert("in onSuccess used only for remote editing:" +
                                  "\nresponseText=" + jqXHR.responseText +
                                  "\n\nWe can verify the server response and return false in case of" +
                                  " error response. return true confirm that the response is successful");
                            // we can verify the server response and interpret it do as an error
                            // in the case we should return false. In the case onError will be called
                            return true;
                        },
                        onError: function (rowid, jqXHR, textStatus) {
                            // the function will be used as "errorfunc" parameter of editRow function
                            // (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#editrow)
                            // and saveRow function
                            // (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#saverow)
                            alert("in onError used only for remote editing:" +
                                  "\nresponseText=" + jqXHR.responseText +
                                  "\nstatus=" + jqXHR.status +
                                  "\nstatusText" + jqXHR.statusText +
                                  "\n\nWe don't need return anything");
                        },
                        afterSave: function (rowid) {
                            alert("in afterSave (Submit): rowid=" + rowid + "\nWe don't need return anything");
                        },
                        afterRestore: function (rowid) {
                            alert("in afterRestore (Cancel): rowid=" + rowid + "\nWe don't need return anything");
                        },
                        delOptions: {
                            // because I use "local" data I don't want to send the changes to the server
                            // so I use "processing:true" setting and delete the row manually in onclickSubmit
                            onclickSubmit: function (rp_ge, rowid) {
                                // we can use onclickSubmit function as "onclick" on "Delete" button
                                alert("The row with rowid=" + rowid + " will be deleted");

                                // reset processing which could be modified
                                rp_ge.processing = true;

                                // delete row
                                grid.delRowData(rowid);
                                $("#delmod" + grid[0].id).hide();

                                if (grid[0].p.lastpage > 1) {
                                    // reload grid to make the row from the next page visable.
                                    // TODO: deleting the last row from the last page which number is higher as 1
                                    grid.trigger("reloadGrid", [{ page: grid[0].p.page }]);
                                }

                                return true;
                            },
                            processing: true // !!! the most important step for the "local" editing
                            //     skip ajax request to the server
                        }
                    }
                },
                ///
                { name: "QuotationDetailID", hidden: true },
                { name: "QuotationID", hidden: true },
                { name: "ServiceID", hidden: true },
                { name: "ServiceDescription", width: 150, editable: true },
                { name: "Unit", width: 75, editable: true },
                { name: "Rate", width: 75, editable: true },
                { name: "Discount", width: 75, editable: true },
                { name: "Frequency", width: 150, editable: true },
                { name: "FrequencyBase", width: 150, editable: true },
                { name: "Total", width: 150, editable: true },
            ],
            rowNum: 10,
            rowList: [5, 10, 20],
            pager: '#gridViewEditablePager',
            gridview: true,
            rownumbers: true,
            ignoreCase: true,
            //sortname: 'invdate',
            viewrecords: true,
            //sortorder: "desc",
            caption: "Quotation Services",
            height: "100%",
            editurl: 'clientArray',
            ondblClickRow: function (id, ri, ci) {
                // edit the row and save it on press "enter" key
                grid.jqGrid('editRow', id, true, null, null, 'clientArray');
            },
            onSelectRow: function (id) {
                if (id && id !== lastSel) {
                    // cancel editing of the previous selected row if it was in editing state.
                    // jqGrid hold intern savedRow array inside of jqGrid object,
                    // so it is safe to call restoreRow method with any id parameter
                    // if jqGrid not in editing state
                    if (typeof lastSel !== "undefined") {
                        grid.jqGrid('restoreRow', lastSel);
                    }
                    lastSel = id;
                }
            }
        }).jqGrid('navGrid', '#gridViewEditablePager', { add: false, edit: false }, {},{}, myDelOptions, { multipleSearch: true, overlay: false });

如上所述,在您的用例中,您需要提供实现类型类的隐式对象FooAble&amp; BarAble和函数trait Addable[T] { def zero: T def append(a: T, b: T): T } trait Productable[T] { def zero: T def product(a: T, b: T): T } implicit object IntIsAddable extends Addable[Int] { def zero = 0 def append(a: Int, b: Int) = a + b } implicit object IntIsProductable extends Productable[Int] { def zero = 1 def product(a: Int, b: Int) = a*b } def sumAndProduct[T](xs: List[T])(implicit addable: Addable[T], productable: Productable[T]) = (xs.foldLeft(addable.zero)(addable.append), xs.foldLeft(productable.zero)(productable.product)) 的方法签名变为:

f