在尝试在整个项目中使用类型类时,我遇到了以下问题。
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
的元素实现类型FooAble
和BarAble
?
答案 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