So I have code that looks similar to this toy example in a Common Lisp project:<div><br></div><div><div><br></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>
(defgeneric to-list (data)</div></div><div><div> (:documentation "Convert given data type to a proper list"))</div></div><div><div><br></div></div><div><div>(defmethod to-list ((data list))</div></div><div><div>
list)</div></div><div><div><br></div></div><div><div>(defmethod to-list ((data vector))</div></div><div><div> (coerce data 'list))</div></div><div><div><br></div></div><div><div>(defmethod to-list ((data binary-tree))</div>
</div><div><div> (traverse #'(lambda (x) x) data 'in-order))</div></div><div><br></div><div>;;; ... So on for other collection datatypes ...</div><div><br></div></blockquote><div><br></div><div>This way I can write a function to work on multiple collection types without having to define multiple methods to specialize on each. In addition it allows me to define TO-LIST method for any future types I would to use those functions on. From what I understand this would be done similarly in Haskell with a type-class:</div>
<div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>class Listable a where</div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>toList :: a -> [b]</div><div><br></div></blockquote></blockquote>But I am not a Haskell expert, and my code doesn't literally have TO-LIST.<div><br>
</div><div>I see that Racket has generic functions, but they see to work a bit differently that CLOS-style generics. Further, like Haskell's type-classes I would like to be able to provide a contract for functions that take a Listable type:</div>
<div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>(provide </div></blockquote><blockquote class="webkit-indent-blockquote" style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div>(contract-out </div></blockquote></blockquote><blockquote class="webkit-indent-blockquote" style="margin:0 0 0 40px;border:none;padding:0px"><blockquote class="webkit-indent-blockquote" style="margin:0 0 0 40px;border:none;padding:0px">
<blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><...> </div></blockquote></blockquote><blockquote class="webkit-indent-blockquote" style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div>[foo (-> listable? bar?)] </div></blockquote></blockquote><blockquote class="webkit-indent-blockquote" style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div><...>))</div></blockquote></blockquote></blockquote><div><br></div>
<div>I can do this in CL using a :BEFORE method</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>(defmethod foo :before ((collection t) <...>) </div>
</blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>(unless (find-method #'to-list () (list (class-of collection)) nil) ; ensure collection object has TO-LIST method</div>
</blockquote></blockquote><blockquote class="webkit-indent-blockquote" style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div>; otherwise raise error condition)</div></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div><...>)</div><div><br></div></blockquote></blockquote>What would be the appropriate Racket construct or idiom to get sort of "type-class" or "interface" that can be enforced through contracts?<div>
<br></div><div>Thanks,</div><div>Helmut<br><div><br><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px">
<div><br></div></blockquote></blockquote><br></div></div>