How can I generalise defaulting across Maybe and Either? - haskell

In Haskell, if I have two functions like this:
defEither ∷ Either l r → r → r
defEither eith defVal = either (const defVal) id eith
and
defMaybe ∷ Maybe a → a → a
defMaybe m d = fromMaybe d m
How do I write a type class (or something to similar effect) such that I can generalise the concept of "defaultable" across both Either and Maybe?
Something like
class Defaultable ???? where
def ∷ a b → b → b

Turns out it was the syntax around creating the instance for Either that was confusing me.
Here is what I finished up with:
class Defaultable a where
def ∷ a b → b → b
instance Defaultable (Either m) where
def e d = either (const d) id e
instance Defaultable Maybe where
def m d = fromMaybe d m
And some tests
def (Just 1) 2
>> 1
def Nothing 2
>> 2
def (Right 2) 5
>> 2
def (Left 3) 5
>> 5
def (Left "Arrghh") 5
>> 5

Related

Haskell - trouble implementing category laws in Quickcheck

I have the category definition:
-- | Cat is the definition of a morphism
type Cat i = i -> i -> Type
-- | Vacuous Constraint
class Vacuous (p :: Cat i) (a :: i)
instance Vacuous p a
class Category (h :: Cat i) where
type Ob h :: i -> Constraint
type Ob h = Vacuous h
id :: Ob h a => h a a
(.) :: h b c -> h a b -> h a c
and I am trying to implement identity and associativity laws for it in QuickCheck, e.g.,
-- | Constraints
type Constraints h a b =
(
Category h, Ob h a,
Arbitrary (h a b), Eq (h a b), Show (h a b)
)
-- | Properties
prop_left_identity :: forall h a b. Constraints h a b => Property
prop_left_identity = property $ \(f:: h a b) -> f. id == f
Issue here is in Eq (h a b), if for instance h = (->), then I will have trouble defining Eq (a -> b) because function equality is not straightforward (I will have issue with unbounded types, and in case of bounded go through all possible inputs and I don't want that). So, I tried avoiding the point free notation and applying f to a, so I can only focus on Eq (b), but I don't have any means to do it. I need a function ap :: h a b -> a -> b but compiler gives an error because b is not of kind Type.
Any ideas about this please 🙏🏻

Most general types in Haskell and defining them

Hello I have a problem with some of my uni Haskell exercises concerning types. I can define types for functions like (*), map etc. but the problem appears when I must define the type of:
f 7 (g 'a')
How I start with this? I know we should use some most general unifier but I didn't find anything about it on the Internet?
Further more there is another task to find most general type taking into account possible classes of types.
foldl (++)
square (f x)
g for function:
g [ ] = Nothing
g [x] = Just x
g (x:y:l) = if x < y then Just x else Just y
What is most general type here? What does it mean in Haskell and what should be done here?
I would be grateful for any explanations. This is not any homework just preparation for exam, any help would be more than welcome.
Start with explicit parentheses:
f 7 (g 'a') == (f 7) (g 'a')
Knowing that 7 :: Num a => a and 'a' :: Char, it's immediately clear that
f :: Num a => a -> b
g :: Char -> c
for some unconstrained types b and c. However, we also know that b is a function type, because the return value of f is applied to the return value of g. Further, we know the return value of g has type c. So we can refine our guess for what b must be:
f :: Num a => a -> (c -> d) -- parentheses are redundant
g :: Char -> c
There's not much else you can do at this point, other than make the following observations:
f 7 :: c -> d
g 'a' :: c
f 7 (g 'a') :: d

How can I express foldr in terms of foldMap for type-aligned sequences?

I'm playing around with type-aligned sequences, and in particular I'm messing around with the idea of folding them. A foldable type-aligned sequence looks something like this:
class FoldableTA fm where
foldMapTA :: Category h =>
(forall b c . a b c -> h b c) ->
fm a b d -> h b d
foldrTA :: (forall b c d . a c d -> h b c -> h b d) ->
h p q -> fm a q r -> h p r
foldlTA :: ...
It's pretty easy to implement foldrTA in terms of foldMapTA by first using foldMapTA to convert the sequence to a type-aligned list in the naive way (i.e., using the type-aligned list category) and then folding over that list. Unfortunately, this can be quite inefficient because long lists may be prepended to short ones. I've been trying to figure out a way to use a trick similar to the one used in Data.Foldable to define the right and left folds more efficiently, but the types are making me dizzy. Endo does not seem general enough to do the trick, and every step I take in other directions leads me to more type variables than I can keep track of.
I found that this typechecks:
{-# LANGUAGE RankNTypes #-}
module FoldableTA where
import Control.Category
import Prelude hiding (id, (.))
class FoldableTA fm where
foldMapTA :: Category h => (forall b c . a b c -> h b c) -> fm a b d -> h b d
foldrTA :: (forall b c d . a c d -> h b c -> h b d) -> h p q -> fm a q r -> h p r
foldrTA f z t = appEndoTA (foldMapTA (\x -> TAEndo (f x)) t) z
newtype TAEndo h c d = TAEndo { appEndoTA :: forall b. h b c -> h b d }
instance Category (TAEndo h) where
id = TAEndo id
TAEndo f1 . TAEndo f2 = TAEndo (f1 . f2)
No idea if it makes any sense, but with so many type indexes around, I doubt that there is much type-checking code that does not make sense.

Haskell's Arrow-Class in Agda and -> in Agda

I have two closely related questions:
First, how can the Haskell's Arrow class be modeled / represented in Agda?
class Arrow a where
arr :: (b -> c) -> a b c
(>>>) :: a b c -> a c d -> a b d
first :: a b c -> a (b,d) (c,d)
second :: a b c -> a (d,b) (d,c)
(***) :: a b c -> a b' c' -> a (b,b') (c,c')
(&&&) :: a b c -> a b c' -> a b (c,c')
(the following Blog Post states that it should be possible...)
Second, in Haskell, the (->) is a first-class citizen and just another higher-order type and its straightforward to define (->) as one instance of the Arrow class. But how is that in Agda? I could be wrong, but I feel, that Agdas -> is a more integral part of Agda, than Haskell's -> is. So, can Agdas -> be seen as a higher-order type, i.e. a type function yielding Set which can be made an instance of Arrow?
Type classes are usually encoded as records in Agda, so you can encode the Arrow class as something like this:
open import Data.Product -- for tuples
record Arrow (A : Set → Set → Set) : Set₁ where
field
arr : ∀ {B C} → (B → C) → A B C
_>>>_ : ∀ {B C D} → A B C → A C D → A B D
first : ∀ {B C D} → A B C → A (B × D) (C × D)
second : ∀ {B C D} → A B C → A (D × B) (D × C)
_***_ : ∀ {B C B' C'} → A B C → A B' C' → A (B × B') (C × C')
_&&&_ : ∀ {B C C'} → A B C → A B C' → A B (C × C')
While you can't refer to the function type directly (something like _→_ is not valid syntax), you can write your own name for it, which you can then use when writing an instance:
_=>_ : Set → Set → Set
A => B = A → B
fnArrow : Arrow _=>_ -- Alternatively: Arrow (λ A B → (A → B)) or even Arrow _
fnArrow = record
{ arr = λ f → f
; _>>>_ = λ g f x → f (g x)
; first = λ { f (x , y) → (f x , y) }
; second = λ { f (x , y) → (x , f y) }
; _***_ = λ { f g (x , y) → (f x , g y) }
; _&&&_ = λ f g x → (f x , g x)
}
While hammar's answer is a correct port of the Haskell code, the definition of _=>_ is too limited compared to ->, since it doesn't support dependent functions. When adapting code from Haskell, that's a standard necessary change if you want to apply your abstractions to the functions you can write in Agda.
Moreover, by the usual convention of the standard library, this typeclass would be called RawArrow because to implement it you do not need to provide proofs that your instance satisfies the arrow laws; see RawFunctor and RawMonad for other examples (note: definitions of Functor and Monad are nowhere in sight in the standard library, as of version 0.7).
Here's a more powerful variant, which I wrote and tested with Agda 2.3.2 and the 0.7 standard library (should also work on version 0.6). Note that I only changed the type declaration of RawArrow's parameter and of _=>_, the rest is unchanged. When creating fnArrow, though, not all alternative type declarations work as before.
Warning: I only checked that the code typechecks and that => can be used sensibly, I didn't check whether examples using RawArrow typecheck.
module RawArrow where
open import Data.Product --actually needed by RawArrow
open import Data.Fin --only for examples
open import Data.Nat --ditto
record RawArrow (A : (S : Set) → (T : {s : S} → Set) → Set) : Set₁ where
field
arr : ∀ {B C} → (B → C) → A B C
_>>>_ : ∀ {B C D} → A B C → A C D → A B D
first : ∀ {B C D} → A B C → A (B × D) (C × D)
second : ∀ {B C D} → A B C → A (D × B) (D × C)
_***_ : ∀ {B C B' C'} → A B C → A B' C' → A (B × B') (C × C')
_&&&_ : ∀ {B C C'} → A B C → A B C' → A B (C × C')
_=>_ : (S : Set) → (T : {s : S} → Set) → Set
A => B = (a : A) -> B {a}
test1 : Set
test1 = ℕ => ℕ
-- With → we can also write:
test2 : Set
test2 = (n : ℕ) → Fin n
-- But also with =>, though it's more cumbersome:
test3 : Set
test3 = ℕ => (λ {n : ℕ} → Fin n)
--Note that since _=>_ uses Set instead of being level-polymorphic, it's still
--somewhat limited. But I won't go the full way.
--fnRawArrow : RawArrow _=>_
-- Alternatively:
fnRawArrow : RawArrow (λ A B → (a : A) → B {a})
fnRawArrow = record
{ arr = λ f → f
; _>>>_ = λ g f x → f (g x)
; first = λ { f (x , y) → (f x , y) }
; second = λ { f (x , y) → (x , f y) }
; _***_ = λ { f g (x , y) → (f x , g y) }
; _&&&_ = λ f g x → (f x , g x)
}

writing functions in haskell that work on associated types only

I'm trying to find a more elegant way to write the following code.
class C c where
type E c :: * -> *
class C c => A c where
g :: E c a -> E c a
class (C c, A c) => D c where
f :: E c a -> E c a
instance A c => D c where
f = g
This produces an error.
Test.hs:58:9:
Could not deduce (E c0 ~ E c)
from the context (A c)
bound by the instance declaration at Test.hs:57:10-19
NB: `E' is a type function, and may not be injective
Expected type: E c a
Actual type: E c0 a
Expected type: E c a -> E c a
Actual type: E c0 a -> E c0 a
In the expression: g
In an equation for `f': f = g
Failed, modules loaded: none.
My current solution is to add a dummy variable, from which it can derive
which particular C is in use.
class C c where
type E c :: * -> *
class C c => A c where
g_inner :: c -> E c a -> E c a
g = g_inner undefined
class (C c, A c) => D c where
f_inner :: c -> E c a -> E c a
f = f_inner undefined
instance A c => D c where
f_inner = g_inner
I know this is another instance of associated types not being injective,
but I can't quite figure it out. Sure, E might not be injective, but it
seems somewhere the information that g will work on the particular
(E c) referenced in class D has been lost.
Any explanation, and more importantly better workarounds would be
much appreciated. Thanks!
edit
Okay, I see switching type to data makes the code work.
I'm trying to sound out how this might work. Each c creates a new data type E c. In the instance context, we have to match forall a. ((E) c) a -> ((E) c) a with forall a. ((E) c) a -> ((E) c) a. Denoting F = E c, we are then matching forall a. F a -> F a with itself.
I'm having trouble seeing where things break with the type synonyms (associated types) case. Sure, one could define two instances of A which both have signature (E c) a -> (E c) a. But, why would it be wrong to use the definition from the instance A c which is in scope?
Thanks!!
The problem is that, from just E c a -> E c a, the compiler doesn't know which instance C to choose.
Associated type families are just type synonyms. So the class
class C c => A c where
g :: E c a -> E c a
from the typechecker's perspective may as well be
class C c => A c where
g :: m a -> m a
As the class variable c isn't mentioned, there's no way to determine which instance dictionary should be used to select the function. Although this is because type families aren't injective, I agree that it isn't obvious from the error message that this is the problem.
Using a data family as Daniel Wagner suggests may be the most elegant solution. I've sometimes been able to invert my type families, so that instead of getting an E c for a particular c, I instead choose c based on E c. In this case, that would give:
class E (e :: * -> *) where
type C e :: *
class E e => A e where
g :: e a -> e a
class (A e) => D e where
f :: e a -> e a
instance A e => D e where
f = g
Depending on what else you're doing, this may work for you.
This problem aside, having a separate instance doesn't make much sense. Since A is available as a super class constraint, you can just set f = g as a default method. Doing so will be much less trouble; you probably don't actually want an instance D e where ....

Resources