- fomo sacer
- Feb 14, 2007
-
|
Does anyone have a good resource for gaining an understanding of category theory for code bros who know almost nothing about math? It's OK if this isn't a thing, but if it is I'd appreciate a recommendation for a decent resource.
I like Categories For Scientists (edit: here is the current edition of the book from the publisher's website as ugly HTML instead of an ugly pdf) as a gentle/somewhat practical survey of category theory. It may end up being more math-y than you're looking for but it's also free on the internet, so worth taking a peek at.
fomo sacer fucked around with this message at 00:46 on Nov 19, 2016
|
#
¿
Nov 18, 2016 16:18
|
|
- Adbot
-
ADBOT LOVES YOU
|
|
#
¿
May 14, 2024 20:31
|
|
- fomo sacer
- Feb 14, 2007
-
|
While playing around with generic execution models I ran into the following, a typeclass with a function that returns another instance of that typeclass:
code:class Processor a where
process :: Processor b => a -> Int -> b
data P = P Int
instance Processor P where
process (P x) y = P y
-- can't return P because it's no Processor
-- more precise, but pointless
instance (Processor P) => Processor P where
process (P x) y = P y
Is there a way to achieve something like this in Haskell? Type families maybe? I'm not up to speed on all extensions...
The way you've written Processor is requiring that a Processor can be turned into any other instance of Processor by calling process on it, i.e. the return type of process needs to be polymorphic, but when you wrote the instance for P, you fixed the return type as P.
You can fix this by requiring Processors to provide you with a generic constructor function:
code:class Processor a where
fromInt :: Int -> a
process :: Processor b => a -> Int -> b
data P = P Int
instance Processor P where
fromInt = P
process (P a) b = fromInt b
Alternatively, you can use multi-parameter type classes to represent the idea that one type can be processed into another type:
code:{-# Language MultiParamTypeClasses #-}
class Processor a b where
process :: a -> Int -> b
data P = P Int
data Q = Q Int
instance Processor P Q where
process (P a) b = Q (a*b)
instance Processor Q P where
process (Q a) b = P (a+b)
In this case, GHC may have trouble with type inference unless you sprinkle type annotations all over your code. You can avoid this with functional dependencies, at the cost of some flexibility:
code:{-# Language MultiParamTypeClasses #-}
{-# Language FunctionalDependencies #-}
class Processor a b | a -> b where -- a determines b. b -> a is also possible
process :: a -> Int -> b
data P = P Int
data Q = Q Int
instance Processor P Q where
process (P a) b = Q (a*b)
instance Processor Q P where
process (Q a) b = P (a+b)
instance Processor P P where -- not allowed, we already have an instance of Processor P _
process = undefined
fomo sacer fucked around with this message at 00:57 on May 21, 2017
|
#
¿
May 20, 2017 16:06
|
|