summaryrefslogtreecommitdiff
path: root/Haskell-book/21/instances
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2025-12-11 10:28:11 +0100
committerEugen Wissner <belka@caraus.de>2025-12-11 10:28:11 +0100
commit98329e0a3dd4f78b5d815ac3896272ec70904901 (patch)
tree80f9c56cfe2ac20232358f236d32e84bd683be1b /Haskell-book/21/instances
parent3624c712d72d246f21d4e710cec7c11e052e0326 (diff)
downloadbook-exercises-98329e0a3dd4f78b5d815ac3896272ec70904901.tar.gz
Add remaining haskell book exercises
Diffstat (limited to 'Haskell-book/21/instances')
-rw-r--r--Haskell-book/21/instances/.gitignore3
-rw-r--r--Haskell-book/21/instances/LICENSE30
-rw-r--r--Haskell-book/21/instances/Setup.hs2
-rw-r--r--Haskell-book/21/instances/package.yaml24
-rw-r--r--Haskell-book/21/instances/src/Lib.hs222
-rw-r--r--Haskell-book/21/instances/src/SkiFree.hs32
-rw-r--r--Haskell-book/21/instances/src/Tree.hs44
-rw-r--r--Haskell-book/21/instances/stack.yaml66
-rw-r--r--Haskell-book/21/instances/test/Spec.hs35
9 files changed, 458 insertions, 0 deletions
diff --git a/Haskell-book/21/instances/.gitignore b/Haskell-book/21/instances/.gitignore
new file mode 100644
index 0000000..5273565
--- /dev/null
+++ b/Haskell-book/21/instances/.gitignore
@@ -0,0 +1,3 @@
+.stack-work/
+instances.cabal
+*~ \ No newline at end of file
diff --git a/Haskell-book/21/instances/LICENSE b/Haskell-book/21/instances/LICENSE
new file mode 100644
index 0000000..e037c72
--- /dev/null
+++ b/Haskell-book/21/instances/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2018
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of Author name here nor the names of other
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Haskell-book/21/instances/Setup.hs b/Haskell-book/21/instances/Setup.hs
new file mode 100644
index 0000000..9a994af
--- /dev/null
+++ b/Haskell-book/21/instances/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Haskell-book/21/instances/package.yaml b/Haskell-book/21/instances/package.yaml
new file mode 100644
index 0000000..11b92bb
--- /dev/null
+++ b/Haskell-book/21/instances/package.yaml
@@ -0,0 +1,24 @@
+name: instances
+version: 0.1.0.0
+author: "Eugen Wissner"
+maintainer: "belka@caraus.de"
+copyright: "2018 Eugen Wissner"
+
+dependencies:
+- base >= 4.7 && < 5
+- QuickCheck
+- checkers
+
+library:
+ source-dirs: src
+
+tests:
+ instances-test:
+ main: Spec.hs
+ source-dirs: test
+ ghc-options:
+ - -threaded
+ - -rtsopts
+ - -with-rtsopts=-N
+ dependencies:
+ - instances
diff --git a/Haskell-book/21/instances/src/Lib.hs b/Haskell-book/21/instances/src/Lib.hs
new file mode 100644
index 0000000..1fbb25b
--- /dev/null
+++ b/Haskell-book/21/instances/src/Lib.hs
@@ -0,0 +1,222 @@
+module Lib where
+
+import Data.Monoid
+import Data.Traversable
+import Test.QuickCheck
+import Test.QuickCheck.Checkers
+
+--
+-- Identity
+--
+newtype Identity a = Identity a
+ deriving (Eq, Ord, Show)
+
+instance Functor Identity where
+ fmap f (Identity x) = Identity $ f x
+
+instance Applicative Identity where
+ pure = Identity
+ (Identity f) <*> x = fmap f x
+
+instance Foldable Identity where
+ foldr f acc (Identity x) = f x acc
+
+instance Arbitrary a => Arbitrary (Identity a) where
+ arbitrary = fmap Identity $ arbitrary
+
+instance Eq a => EqProp (Identity a) where
+ (=-=) = eq
+
+instance Traversable Identity where
+ traverse f (Identity x) = Identity <$> f x
+
+--
+-- Constant
+--
+newtype Constant a b = Constant { getConstant :: a }
+ deriving (Eq, Ord, Show)
+
+instance Functor (Constant a) where
+ fmap _ (Constant x) = Constant x
+
+instance Monoid a => Applicative (Constant a) where
+ pure _ = Constant mempty
+ (Constant x) <*> (Constant y) = Constant $ mappend x y
+
+instance (Arbitrary a, Arbitrary b) => Arbitrary (Constant a b) where
+ arbitrary = do
+ x <- arbitrary
+ return $ Constant x
+
+instance (Eq a, Eq b) => EqProp (Constant a b) where
+ (=-=) = eq
+
+instance Foldable (Constant a) where
+ foldMap _ (Constant _) = mempty
+
+instance Traversable (Constant a) where
+ traverse f (Constant x) = pure $ Constant x
+
+--
+-- Maybe
+--
+data Optional a = Nada | Yep a deriving (Show, Eq, Ord)
+
+instance Monoid a => Monoid (Optional a) where
+ mempty = Nada
+ mappend Nada _ = Nada
+ mappend _ Nada = Nada
+ mappend (Yep x) (Yep y) = Yep $ mappend x y
+
+instance Applicative Optional where
+ pure = Yep
+ (Yep f) <*> (Yep x) = Yep $ f x
+ Nada <*> (Yep x) = Nada
+ _ <*> Nada = Nada
+
+instance Functor Optional where
+ fmap _ Nada = Nada
+ fmap f (Yep x) = Yep $ f x
+
+instance Foldable Optional where
+ foldr f acc Nada = acc
+ foldr f acc (Yep x) = f x acc
+
+instance Traversable Optional where
+ traverse f Nada = pure Nada
+ traverse f (Yep x) = Yep <$> f x
+
+instance (CoArbitrary a, Arbitrary a) => Arbitrary (Optional a) where
+ arbitrary = do
+ x <- arbitrary
+ frequency [ (1, return Nada)
+ , (2, return $ Yep x)
+ ]
+
+instance (Eq a) => EqProp (Optional a) where
+ (=-=) = eq
+
+--
+-- List
+--
+data List a = Nil | Cons a (List a) deriving (Eq, Show)
+
+instance Functor List where
+ fmap _ Nil = Nil
+ fmap f (Cons x xs) = Cons (f x) (fmap f xs)
+
+instance Foldable List where
+ foldr _ acc Nil = acc
+ foldr f acc (Cons x xs) = f x (foldr f acc xs)
+
+instance Traversable List where
+ sequenceA Nil = pure Nil
+ sequenceA (Cons x xs) = Cons <$> x <*> (sequenceA xs)
+
+instance Arbitrary a => Arbitrary (List a) where
+ arbitrary = sized go
+ where go 0 = pure Nil
+ go n = do
+ xs <- go (n - 1)
+ x <- arbitrary
+ return $ Cons x xs
+
+instance (Eq a) => EqProp (List a) where
+ (=-=) = eq
+
+--
+-- Three
+--
+data Three a b c = Three a b c deriving (Show, Eq)
+
+instance Functor (Three a b) where
+ fmap f (Three x y z) = Three x y (f z)
+
+instance Foldable (Three a b) where
+ foldr f acc (Three x y z) = (f z acc)
+
+instance Traversable (Three a b) where
+ traverse f (Three x y z) = fmap (Three x y) (f z)
+
+instance (Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (Three a b c) where
+ arbitrary = do
+ x <- arbitrary
+ y <- arbitrary
+ z <- arbitrary
+ return $ Three x y z
+
+instance (Eq a, Eq b, Eq c) => EqProp (Three a b c) where
+ (=-=) = eq
+
+--
+-- Pair
+--
+data Pair a b = Pair a b deriving (Eq, Show)
+
+instance Functor (Pair a) where
+ fmap f (Pair x y) = Pair x (f y)
+
+instance Foldable (Pair a) where
+ foldr f acc (Pair x y) = (f y acc)
+
+instance Traversable (Pair a) where
+ traverse f (Pair x y) = fmap (Pair x) (f y)
+
+instance (Arbitrary a, Arbitrary b) => Arbitrary (Pair a b) where
+ arbitrary = do
+ x <- arbitrary
+ y <- arbitrary
+ return $ Pair x y
+
+instance (Eq a, Eq b) => EqProp (Pair a b) where
+ (=-=) = eq
+
+--
+-- Big
+--
+data Big a b = Big a b b deriving (Eq, Show)
+
+instance Functor (Big a) where
+ fmap f (Big x y z) = Big x (f y) (f z)
+
+instance Foldable (Big a) where
+ foldr f acc (Big _ y z) = (f y (f z acc))
+
+instance Traversable (Big a) where
+ traverse f (Big x y z) = (Big x) <$> (f y) <*> (f z)
+
+instance (Arbitrary a, Arbitrary b) => Arbitrary (Big a b) where
+ arbitrary = do
+ x <- arbitrary
+ y <- arbitrary
+ z <- arbitrary
+ return $ Big x y z
+
+instance (Eq a, Eq b) => EqProp (Big a b) where
+ (=-=) = eq
+
+--
+-- Bigger
+--
+data Bigger a b = Bigger a b b b deriving (Eq, Show)
+
+instance Functor (Bigger a) where
+ fmap f (Bigger x y z t) = Bigger x (f y) (f z) (f t)
+
+instance Foldable (Bigger a) where
+ foldr f acc (Bigger _ y z t) = f y $ f z $ f t acc
+
+instance Traversable (Bigger a) where
+ traverse f (Bigger x y z t) = (Bigger x) <$> (f y) <*> (f z) <*> (f t)
+
+instance (Arbitrary a, Arbitrary b) => Arbitrary (Bigger a b) where
+ arbitrary = do
+ x <- arbitrary
+ y <- arbitrary
+ z <- arbitrary
+ t <- arbitrary
+ return $ Bigger x y z t
+
+instance (Eq a, Eq b) => EqProp (Bigger a b) where
+ (=-=) = eq
+
diff --git a/Haskell-book/21/instances/src/SkiFree.hs b/Haskell-book/21/instances/src/SkiFree.hs
new file mode 100644
index 0000000..70e87dc
--- /dev/null
+++ b/Haskell-book/21/instances/src/SkiFree.hs
@@ -0,0 +1,32 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module SkiFree where
+
+import Test.QuickCheck
+import Test.QuickCheck.Checkers
+
+data S n a = S (n a) a deriving (Eq, Show)
+
+instance ( Functor n
+ , Arbitrary (n a)
+ , Arbitrary a)
+ => Arbitrary (S n a) where
+ arbitrary = S <$> arbitrary <*> arbitrary
+
+--instance ( Applicative n
+-- , Testable (n Property)
+-- , EqProp a)
+-- => EqProp (S n a) where
+-- (S x y) =-= (S p q) =
+-- (property $ (=-=) <$> x <*> p) .&. (y =-= q)
+instance (Eq (n a), Eq a) => EqProp (S n a) where
+ (=-=) = eq
+
+instance Functor n => Functor (S n) where
+ fmap f (S x y) = S (fmap f x) (f y)
+
+instance Foldable n => Foldable (S n) where
+ foldMap f (S n a) = mappend (foldMap f n) (f a)
+
+instance Traversable n => Traversable (S n) where
+ traverse f (S x y) = S <$> (traverse f x) <*> (f y)
diff --git a/Haskell-book/21/instances/src/Tree.hs b/Haskell-book/21/instances/src/Tree.hs
new file mode 100644
index 0000000..5c0740c
--- /dev/null
+++ b/Haskell-book/21/instances/src/Tree.hs
@@ -0,0 +1,44 @@
+module Tree where
+
+import Data.Monoid
+import Test.QuickCheck
+import Test.QuickCheck.Checkers
+import Test.QuickCheck.Classes
+
+-- Solution:
+-- https://www.reddit.com/r/HaskellBook/comments/7w7bqn/ch_21_is_this_a_sane_instance_of_traversable/
+
+data Tree a = Empty
+ | Leaf a
+ | Node (Tree a) a (Tree a)
+ deriving (Eq, Show)
+
+instance Functor Tree where
+ fmap _ Empty = Empty
+ fmap f (Leaf x) = Leaf $ f x
+ fmap f (Node x y z) = Node (fmap f x) (f y) (fmap f z)
+
+-- foldMap is a bit easier and looks more natural, but you can do
+-- foldr too for extra credit.
+instance Foldable Tree where
+ foldMap _ Empty = mempty
+ foldMap f (Leaf x) = f x
+ foldMap f (Node x y z) = (foldMap f x) <> (f y) <> (foldMap f z)
+
+instance Traversable Tree where
+ traverse f Empty = pure Empty
+ traverse f (Leaf x) = Leaf <$> f x
+ traverse f (Node x y z) = Node <$> (traverse f x) <*> (f y) <*> (traverse f z)
+
+instance Arbitrary a => Arbitrary (Tree a) where
+ arbitrary = do
+ x <- arbitrary
+ y <- arbitrary
+ z <- arbitrary
+ frequency [ (1, return Empty)
+ , (2, return $ Leaf y)
+ , (3, return $ Node x y z)
+ ]
+
+instance Eq a => EqProp (Tree a) where
+ (=-=) = eq
diff --git a/Haskell-book/21/instances/stack.yaml b/Haskell-book/21/instances/stack.yaml
new file mode 100644
index 0000000..35d283a
--- /dev/null
+++ b/Haskell-book/21/instances/stack.yaml
@@ -0,0 +1,66 @@
+# This file was automatically generated by 'stack init'
+#
+# Some commonly used options have been documented as comments in this file.
+# For advanced use and comprehensive documentation of the format, please see:
+# https://docs.haskellstack.org/en/stable/yaml_configuration/
+
+# Resolver to choose a 'specific' stackage snapshot or a compiler version.
+# A snapshot resolver dictates the compiler version and the set of packages
+# to be used for project dependencies. For example:
+#
+# resolver: lts-3.5
+# resolver: nightly-2015-09-21
+# resolver: ghc-7.10.2
+# resolver: ghcjs-0.1.0_ghc-7.10.2
+# resolver:
+# name: custom-snapshot
+# location: "./custom-snapshot.yaml"
+resolver: lts-10.5
+
+# User packages to be built.
+# Various formats can be used as shown in the example below.
+#
+# packages:
+# - some-directory
+# - https://example.com/foo/bar/baz-0.0.2.tar.gz
+# - location:
+# git: https://github.com/commercialhaskell/stack.git
+# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
+# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
+# extra-dep: true
+# subdirs:
+# - auto-update
+# - wai
+#
+# A package marked 'extra-dep: true' will only be built if demanded by a
+# non-dependency (i.e. a user package), and its test suites and benchmarks
+# will not be run. This is useful for tweaking upstream packages.
+packages:
+- .
+# Dependency packages to be pulled from upstream that are not in the resolver
+# (e.g., acme-missiles-0.3)
+# extra-deps: []
+
+# Override default flag values for local packages and extra-deps
+# flags: {}
+
+# Extra package databases containing global packages
+# extra-package-dbs: []
+
+# Control whether we use the GHC we find on the path
+# system-ghc: true
+#
+# Require a specific version of stack, using version ranges
+# require-stack-version: -any # Default
+# require-stack-version: ">=1.6"
+#
+# Override the architecture used by stack, especially useful on Windows
+# arch: i386
+# arch: x86_64
+#
+# Extra directories used by stack for building
+# extra-include-dirs: [/path/to/dir]
+# extra-lib-dirs: [/path/to/dir]
+#
+# Allow a newer minor version of GHC than the snapshot specifies
+# compiler-check: newer-minor \ No newline at end of file
diff --git a/Haskell-book/21/instances/test/Spec.hs b/Haskell-book/21/instances/test/Spec.hs
new file mode 100644
index 0000000..934b120
--- /dev/null
+++ b/Haskell-book/21/instances/test/Spec.hs
@@ -0,0 +1,35 @@
+import Lib
+import Data.Monoid
+import Test.QuickCheck
+import Test.QuickCheck.Checkers
+import Test.QuickCheck.Classes
+import SkiFree
+import Tree
+
+main :: IO ()
+main = do
+ sample' (arbitrary :: Gen (S [] Int))
+
+ quickBatch $ traversable $ (Identity (['a'], ['b'], ['c']))
+
+ quickBatch $ applicative $ (undefined :: Constant (String, String, String) (String, String, String))
+ quickBatch $ traversable $ (undefined :: Constant (String, String, String) (String, String, String))
+
+ quickBatch $ traversable $ (undefined :: Optional (String, String, String))
+
+ quickBatch $ traversable $ (undefined :: List (String, String, String))
+
+ quickBatch $ traversable $ (undefined :: Three (String, String, String)
+ (String, String, String)
+ (String, String, String))
+ quickBatch $ traversable $ (undefined :: Pair (String, String, String)
+ (String, String, String))
+ quickBatch $ traversable $ (undefined :: Big (String, String, String)
+ (String, String, String))
+ quickBatch $ traversable $ (undefined :: Bigger (String, String, String)
+ (String, String, String))
+
+ quickBatch $ functor $ S [("a", "q", "y")] ("a", "b", "c")
+ quickBatch $ traversable $ S [("a", "q", "y")] ("a", "b", "c")
+
+ quickBatch $ traversable $ Leaf ("a", "q", "y")