Now I'm reading next book about Scala and found some exercises for self-evaluation.
Page 27, exercise 2.7:
Let's look at another example, currying, which converts a finction f of two arguments into a function of one argument that partially applies f. Here again there's only one implementation that compiles. Write this implementation
def curry[A, B, C](f: (A, B) => C): A => (B => C) = ...
It's really important to mention, that exercise says about only one possible implementation, that compiles. If book mean that there is physically only one option, then I don't understand why the book says there is only one solution.
For example, solution from book:
def curry[A, B, C](f: (A, B) => C): A => (B => C) = a => b => f(a,b)
And my own one:
def curry[A, B, C](f: (A, B) => C): A => (B => C) = a => f(a, _)
Both variants were successfully compiled. So,let me introduce my vision of solution:
Let's imagine next category:
f - morphism which defined via f: (A, B) → C
g - morphism which defined via g: B → C
l - morphism which defined via l: A → C
As I understand such category, we have next expression for function output:
A → (B → C) = A → C
Such transition can be done because of composition property of category. And that's why I'm used more short expression for A → (B → C as a => f(a, _).
Do I understand it correct?
Related
The statement of the problem.
Consider this definition of map:
Fixpoint map (xs: list nat): (nat -> nat) -> list nat := match xs with
| nil => fun _ => nil
| x::xs' => fun f => (f x) :: (map xs' f)
end.
It works like this:
Coq < Eval simpl in map (1::2::3::List.nil) (fun x => x + 1).
= 2 :: 3 :: 4 :: nil
: list nat
How can I extend it to work on any types?
For example, in Haskell I can simply write as follows:
map :: forall a b. [a] -> (a -> b) -> [b]
map xs = case xs of
[ ] -> \_ -> [ ]
(x:xs') -> \f -> f x: map xs' f
But in Coq, I do not understand where I could place this forall quantifier.
My efforts.
The syntax reference explains the syntax of Fixpoint thusly:
Fixpoint ident binders {struct ident}? : type? := term
— So evidently there is no place in the syntax for a quantifier that binds a type variable over both binders and type. I tried placing forall here and there by guesswork but I could not make it work.
I can see how the type section could be made polymorphic in the result type of the function parameter without touching the binders section:
Fixpoint map (xs: list nat): forall B, (nat -> B) -> list B := match xs with
| nil => fun _ => nil
| x::xs' => fun f => f x :: (map xs' f)
end.
— But unfortunately this also gives an error, and cryptic enough for me at that:
In environment
map : list nat -> forall B : Type, (nat -> B) -> list B
xs : list nat
T : Type
The term "nil" has type "list ?A" while it is expected to have type
"(nat -> T) -> list T".
So, even for this simpler case I have no solution.
So, what can be done?
In Coq, the Fixpoint command is just a wrapper around the fix term constructor, which allows us to define anonymous recursive functions. A direct definition of map could be given as follows:
Require Import Coq.Lists.List.
Import ListNotations.
Definition map_anon : forall A B, (A -> B) -> list A -> list B :=
fix map A B (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map A B f l
end.
This is morally equivalent to the following definition:
Fixpoint map A B (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map A B f l
end.
Notice that A and B are bound as regular variables: in Coq, there is no distinction between types and terms, and these declarations causes Coq to infer their types as being Type. No forall quantifier is needed for the definition.
You can list all your arguments, including type arguments, after the name of the function. You'll put any arguments that depend on other arguments after the argument they depend on.
Fixpoint map (A B: Type) (xs: list A) (f: A -> B): list B :=
[...]
If you prefer foralls, you simply need to move everything (except the recursive argument and any arguments it depends on) to after the :.
Fixpoint map (A B: Type) (xs: list A): forall (f: A -> B), list B :=
[...]
Two things to note here. Since nothing after f depends on f, you could use the -> notation. This is purely notation and doesn't have any semantic difference.
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
[...]
The other thing to note is that when the arguments are after the : like this, we have to define a function, not just something in list B.
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
fun f => [...]
This is why you got the error The term "nil" has type "list ?A" while it is expected to have type "(nat -> T) -> list T".. We needed a function, not just something of type list B, which is what nil is.
I have the following problem. My equation is:
NAND2(NAND4(d,c,-b,a),NAND2(c,-a))
the "-" represents "NOT". I am not allowed to use NAND4, I am only allowed to use NAND2.
How do I convert this?
Thanks
NAND in general is equivalent to NOT(AND(…))
AND4(a, b, c, d) is equivalent to AND2(AND2(a, b), AND2(c, d))
NAND4(a, b, c, d) is thus equivalent to NOT(AND4(a, b, c, d)) and that’s equivalent to NOT(AND2(AND2(a, b), AND2(c, d)))
This is equivalent to NAND2(AND2(a, b), AND2(c, d))
If you were only allowed to use NANDs but not ANDs, you could invert the ANDs there: NAND2(NOT(NAND2(a, b)), NOT(NAND2(c, d)))
In these implementations of curry and compose :
def uncurry[A,B,C] (f : (A => B => C)) : (A , B) => C = (a , b) => f(a) (b)
def compose [A ,B , C] (f : B => C , g : A => B) : A => C = (a : A) => f(g(a))
In compose implementation is (a : A) just syntactic sugar for (a) as
def compose [A ,B , C] (f : B => C , g : A => B) : A => C = (a : A) => f(g(a))
compiles without issue ?
Yes, but is the other way around: (a) is syntactic sugar for (a:A), since the compiler can infer that a is of type A. You don't even need the parenthesis for (a):
def compose [A ,B , C] (f : B => C , g : A => B) : A => C = a => f(g(a))
Not necessarily related to the question, but for this particular case, that functionality is already available, so you can just do:
def compose [A ,B , C] (f : B => C , g : A => B) : A => C = f compose g
Using :i Map, I don't see a Monad instance for it.
ghci> import Data.Map
ghci> :i Map
type role Map nominal representational
data Map k a
= containers-0.5.5.1:Data.Map.Base.Bin {-# UNPACK #-} !containers-0.5.5.1:Data.Map.Base.Size
!k
a
!(Map k a)
!(Map k a)
| containers-0.5.5.1:Data.Map.Base.Tip
-- Defined in ‘containers-0.5.5.1:Data.Map.Base’
instance (Eq k, Eq a) => Eq (Map k a)
-- Defined in ‘containers-0.5.5.1:Data.Map.Base’
instance Functor (Map k)
-- Defined in ‘containers-0.5.5.1:Data.Map.Base’
instance (Ord k, Ord v) => Ord (Map k v)
-- Defined in ‘containers-0.5.5.1:Data.Map.Base’
instance (Ord k, Read k, Read e) => Read (Map k e)
-- Defined in ‘containers-0.5.5.1:Data.Map.Base’
instance (Show k, Show a) => Show (Map k a)
-- Defined in ‘containers-0.5.5.1:Data.Map.Base
However, I see that Scala's Map implements flatMap.
I do not know if Map if obeys the Monad Laws.
If my observation on Data.Map is correct, then why isn't there an instance Monad (Map) in Haskell?
I looked at this answer, but it looks like it uses Monad Transformers.
It's hard to reason what Scala's flatMap is supposed to do:
trait Map[A, B+] extends Iterable[(A, B)] {
def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Map[B]
}
It takes a key, value pair of map (because flatMap comes from Iterable, where A is (A,B)):
scala> val m = Map("one" -> 1, "two" -> 2)
m: scala.collection.immutable.Map[String,Int] = Map(one -> 1, two -> 2)
scala> m.flatMap (p => p match { case (_, v) => List(v, v + 3) })
res1: scala.collection.immutable.Iterable[Int] = List(1, 4, 2, 5)
This isn't monadic bind, it's more closer to Foldable's foldMap
λ > import Data.Map
λ > import Data.Monoid
λ > import Data.Foldable
λ > let m = fromList [("one", 1), ("two", 2)]
λ > (\v -> [v, v + 3]) `foldMap` m
[1,4,2,5]
Map is lawful Ord k => Apply (Map k v) and Ord k => Bind (Map k v):
-- | A Map is not 'Applicative', but it is an instance of 'Apply'
instance Ord k => Apply (Map k) where
(<.>) = Map.intersectionWith id
(<. ) = Map.intersectionWith const
( .>) = Map.intersectionWith (const id)
-- | A 'Map' is not a 'Monad', but it is an instance of 'Bind'
instance Ord k => Bind (Map k) where
m >>- f = Map.mapMaybeWithKey (\k -> Map.lookup k . f) m
Which is a bit like ZipList instance could be, zipping elements by key. Note: ZipList isn't Bind (only Apply) because you cannot remove elements from between the range.
And you cannot make it Applicative or Monad, because there are no way to make lawful pure / return, which should have a value at all keys. Or it might be possible if some Finite type class is constraining k (because Map is strict in it's spine, so you cannot create infinite maps).
EDIT: pointed out in the comments. If we think properly, the above tries to make a concrete (inspectable) representation of MaybeT (Reader k) v = k -> Maybe v with Map k v. But we fail, as we cannot represent pure x = const x. But we can try to do that by explicitly representing that case:
module MMap (main) where
import Data.Map (Map)
import qualified Data.Map as Map
import Test.QuickCheck
import Test.QuickCheck.Function
import Control.Applicative
import Control.Monad
-- [[ MMap k v ]] ≅ k -> Maybe v
data MMap k v = MConstant v
| MPartial (Map k v)
deriving (Eq, Ord, Show)
-- Morphism
lookup :: Ord k => k -> MMap k v -> Maybe v
lookup _ (MConstant x) = Just x
lookup k (MPartial m) = Map.lookup k m
instance Functor (MMap k) where
fmap f (MConstant v) = MConstant (f v)
fmap f (MPartial m) = MPartial (fmap f m)
instance Ord k => Applicative (MMap k) where
pure = MConstant
(MConstant f) <*> (MConstant x) = MConstant (f x)
(MConstant f) <*> (MPartial x) = MPartial (fmap f x)
(MPartial f) <*> (MConstant x) = MPartial (fmap ($x) f)
(MPartial f) <*> (MPartial x) = MPartial (Map.intersectionWith ($) f x)
instance Ord k => Monad (MMap k) where
return = MConstant
(MConstant x) >>= f = f x
(MPartial m) >>= f = MPartial $ Map.mapMaybeWithKey (\k -> MMap.lookup k . f) m
instance (Ord k, Arbitrary k, Arbitrary v) => Arbitrary (MMap k v) where
arbitrary = oneof [ MConstant <$> arbitrary
, MPartial . Map.fromList <$> arbitrary
]
prop1 :: Int -> Fun Int (MMap Int Int) -> Property
prop1 x (Fun _ f) = (return x >>= f) === f x
prop2 :: MMap Int Int -> Property
prop2 x = (x >>= return) === x
prop3 :: MMap Int Int -> Fun Int (MMap Int Int) -> Fun Int (MMap Int Int) -> Property
prop3 m (Fun _ f) (Fun _ g) = ((m >>= f) >>= g) === (m >>= (\x -> f x >>= g))
main :: IO ()
main = do
quickCheck prop1
quickCheck prop2
quickCheck prop3
It indeed works! Yet this a bit fishy definition, as we cannot define semantically correct Eq instance:
m1 = MConstant 'a'
m2 = MPartial (Map.fromList [(True, 'a'), (False, 'a')])
The m1 are m2 are semantically equivalent (lookup k has same results), but structurally different. And we can't know when MPartial have all key-values defined.
Spine refers to, uh, data structure spine. For example list defined as
data List a = Nil | Cons a (List a)
ins't strict in the spine, but
data SList a = SNil | SCons a !(SList a)
is.
You can define infinite List, but SLists:
λ Prelude > let l = Cons 'a' l
λ Prelude > let sl = SCons 'a' sl
λ Prelude > l `seq` ()
()
λ Prelude > sl `seq` () -- goes into infinite loop
As Map is also strict in it's spine
data Map k a = Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
| Tip
we cannot construct infinite Map, even we had means to get all values of k type. But we can construct infinite ordinary Haskell list: [] to make pure for Applicative ZipList.
No, there is no Monad instance for Map indeed.
I see that Scala's Map implements flatMap.
I assume you notice that alone doesn't make it a monad?
But we can try nonetheless to make Haskell's Map a Monad. How would it intuitively work? We'd map over the values of the map, return a new map for each, and then join together all those maps by using unions. That should work!
Indeed, if we take a closer look at the classes that Map implements we see something very similar:
import Data.Map
import Data.Traversable
import Data.Foldable
import Data.Monoid
where Monoid.mconcat takes the role of our unions, and Traversable offers a foldMapDefault that does exactly what we want (and could be used for >>=)!
However, when we want to implement return we have a problem - there's no key! We get a value, but we cannot make a Map from that! That's the same problem Scala has avoided by making flatMap more generic than a monad. We could solve this by getting a default value for the key, e.g. by requiring the key type to be a Monoid instance, and make an instance (Ord k, Monoid k) => Monad (Map k) with that - but it will fail to satisfy the monad laws because of the limited return.
Still, all the use cases of the overloaded flatMap in Scala are covered by equivalent methods on Haskell Maps. You'll want to have a closer look at mapMaybe/mapMaybeWithkey and foldMap/foldMapWithKey.
How would you implement return for Data.Map? Presumably return x would have x as a value, but with what key(s)?
I started learning Isabelle and wanted to try defining a monoid in Isabelle but don't know how.
In Coq, I would do something like this:
Inductive monoid (τ : Type) (op: τ -> τ -> τ) (i: τ): Prop :=
| axioms: (forall (e: τ), op e i = e) ->
(forall (e: τ), op i e = e) ->
monoid τ op i.
I am not sure how to do the same thing in Isabelle. Conceptually I thought of something like this:
inductive 'a monoid "('a ⇒ 'a ⇒ 'a) ⇒ 'a ⇒ bool" for f i where
axioms: "⟦f e i = e; f i e = e⟧ ⇒ monoid f i"
But, that is not valid in Isabelle.
How do I define inductive predicates with typed parameters in Isabelle ?
I don't know much about Coq, but Isabelle's type system is very different. Isabelle values do not take ‘type parameters’, and Isabelle types do not take ‘value parameters’.
In Isabelle, your example is a simple polymorphic definition which can be done like this:
inductive monoid :: "('a ⇒ 'a ⇒ 'a) ⇒ 'a ⇒ bool" for f i where
axioms: "⟦f e i = e; f i e = e⟧ ⟹ monoid f i"
I must point out that this means that if there exists even one e for which this holds, you have a monoid. What you probably meant to write is
inductive monoid :: "('a ⇒ 'a ⇒ 'a) ⇒ 'a ⇒ bool" for f i where
axioms: "⟦⋀e. f e i = e; ⋀e. f i e = e⟧ ⟹ monoid f i"
Here, the e is universally quantified in the assumptions, meaning the laws must hold for all e in order to constitute a monoid.
Doing this as an inductive definition is possible and has the advantage of automatically generating appropriate introduction/elimination rules (and the ability to generate more with inductive_cases) There are, however, other ways.
Using a Definition
However, you could also write this as a simple definition:
definition monoid :: "('a ⇒ 'a ⇒ 'a) ⇒ 'a ⇒ bool" where
"monoid f i = ((∀e. f e i = e) ∧ (∀e. f i e = e))"
This gives you the definition of monoid as the lemma monoid_def. If you want introduction/elimination rules, you have to derive them yourself.
Using a locale
The third, and probably most suitable solution is that of locales. A locale is a way of keeping certain fixed variables and assumptions in a context and reason within this context. The following example demonstrates how to define a monoid as a locale, derive lemmas in that locale, and then interpret the locale for a concrete example monoid (namely lists) and use the lemmas we proved in the locale for them.
locale monoid =
fixes i :: 'a and f :: "'a ⇒ 'a ⇒ 'a"
assumes left_neutral: "f i e = e"
and right_neutral: "f e i = e"
begin
lemma neutral_unique_left:
assumes "⋀e. f i' e = e"
shows "i' = i"
proof-
from right_neutral have "i' = f i' i" by simp
also from assms have "f i' i = i" by simp
finally show "i' = i" .
qed
end
thm monoid.neutral_unique_left
(* Output: monoid i f ⟹ (⋀e. f i' e = e) ⟹ i' = i *)
(* Let's interpret our monoid for the type "'a list", with []
as neutral element and concatenation (_ # _) as the operation. *)
interpretation list_monoid: monoid "[]" "λxs ys. xs # ys"
by default simp_all
thm list_monoid.neutral_unique_left
(* Output: (⋀e. i' # e = e) ⟹ i' = [] *)
Using a type class
A fourth possibility which is similar to locales it that of type classes. Isabelle supports type classes (like those in Haskell, albeit more restrictive), and you could create a monoid type class and then instantiate it for concrete types like nat, int, 'a list, etc.
More information
For more information on inductive predicates, locales, and type classes, see the documentation of these tools: http://isabelle.in.tum.de/documentation.html