Carp/examples/functor.carp
Scott Olsen b61a439e29 Update test to account for constrained interfaces
Constrained interfaces require little change to core carp. In rare cases
(illustrated in test/interfaces.carp) we need to make our functions
slightly more specific. This weakens inference slightly, but in my
opinion is a reasonable case of weakness and not a fault of the type
system.

Exceptional cases that were typed `a-> a` that is, cases that relied on
the previous typing errors related to interfaces, as might be expected,
no longer work (as is the case for the higher-order use of fmap in
examples/functor.carp).

Aside from that, nothing changes.
2020-06-01 23:39:19 -04:00

41 lines
1.3 KiB
Plaintext

(use IO)
(use Int)
(use Array)
(Project.no-echo)
(definterface fmap (λ [(Ref (λ [a] b)) (f a)] (f b)))
(defmodule ArrayExtension
(defn fmap [f a] (Array.endo-map f a))
(implements fmap ArrayExtension.fmap)
)
(deftype (Box a) [x a])
(defmodule Box
(defn fmap [f box] (let [new-x (~f @(Box.x &box))]
(Box.set-x box new-x)))
(implements fmap Box.fmap))
(use Box)
(use ArrayExtension)
;; TODO: This function currently concretizes to the type of the first (f *) it
;; receives. Is there a way for us to ensure it remains generic?
;; N.B. the only reason it worked previously was because it was ill-typed as
;; (a -> a) which erroneously served as a universal type.
;(sig higherOrder (Fn [(f a)] (f b)))
;(defn higherOrder [x] (fmap &Int.inc x))
(defn main []
(do
(println &(str @(Box.x &(fmap &Int.inc (Box.init 100)))))
(println &(str @(Box.x &(Box.fmap &inc (Box.init 100)))))
(println &(str &(ArrayExtension.fmap &inc [10 20 30 40 50])))
(println &(str &(fmap &Int.inc [10 20 30 40 50])))
(println &(Array.str &(fmap &Int.inc [10 20 30 40 50])))
(println &(Array.str &(ArrayExtension.fmap &Int.inc [10 20 30 40 50])))
;(println &(str &(higherOrder (Box.init 999))))
;(println &(str &(higherOrder [9 99 999 9999])))
))