diff --git a/hw-prim.cabal b/hw-prim.cabal
--- a/hw-prim.cabal
+++ b/hw-prim.cabal
@@ -1,7 +1,7 @@
 cabal-version:  2.2
 
 name:           hw-prim
-version:        0.6.2.25
+version:        0.6.2.26
 synopsis:       Primitive functions and data types
 description:    Primitive functions and data types.
 category:       Data
@@ -73,6 +73,7 @@
     HaskellWorks.Data.Drop
     HaskellWorks.Data.Empty
     HaskellWorks.Data.Filter
+    HaskellWorks.Data.Foldable
     HaskellWorks.Data.FromByteString
     HaskellWorks.Data.FromForeignRegion
     HaskellWorks.Data.Generate
@@ -123,6 +124,7 @@
   main-is: Spec.hs
   other-modules:
     HaskellWorks.Data.ByteStringSpec
+    HaskellWorks.Data.FoldableSpec
     HaskellWorks.Data.FromByteStringSpec
     HaskellWorks.Data.FromForeignRegionSpec
     HaskellWorks.Data.SearchSpec
diff --git a/src/HaskellWorks/Data/Foldable.hs b/src/HaskellWorks/Data/Foldable.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Foldable.hs
@@ -0,0 +1,14 @@
+module HaskellWorks.Data.Foldable
+  ( foldFirst
+  , foldLast
+  ) where
+
+foldFirst :: Foldable t => t a -> Maybe a
+foldFirst = foldr (const . Just) Nothing
+{-# INLINE foldFirst #-}
+
+foldLast :: Foldable t => t a -> Maybe a
+foldLast = foldl go Nothing
+  where go :: Maybe a -> a -> Maybe a
+        go _ = Just
+{-# INLINE foldLast #-}
diff --git a/test/HaskellWorks/Data/FoldableSpec.hs b/test/HaskellWorks/Data/FoldableSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/HaskellWorks/Data/FoldableSpec.hs
@@ -0,0 +1,25 @@
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module HaskellWorks.Data.FoldableSpec (spec) where
+
+import Data.Maybe
+import HaskellWorks.Data.Foldable
+import HaskellWorks.Hspec.Hedgehog
+import Hedgehog
+import Test.Hspec
+
+import qualified Hedgehog.Gen   as G
+import qualified Hedgehog.Range as R
+
+{-# ANN module ("HLint: Ignore Redundant do" :: String) #-}
+
+spec :: Spec
+spec = describe "HaskellWorks.Data.FoldableSpec" $ do
+  it "foldFirst" $ requireProperty $ do
+    as <- forAll $ G.list (R.linear 0 10) (G.int (R.constantBounded))
+    foldFirst as === listToMaybe as
+  it "foldLast" $ requireProperty $ do
+    as <- forAll $ G.list (R.linear 0 10) (G.int (R.constantBounded))
+    foldLast as === listToMaybe (reverse as)
