在命令之后,:set -XTypeApplications我们可以使用GHCi来显示特定实例的类型类函数的特化.
一个简单的例子:
:type fmap @Maybe
Run Code Online (Sandbox Code Playgroud)
GHCi回复
fmap @Maybe :: (a -> b) -> Maybe a -> Maybe b
Run Code Online (Sandbox Code Playgroud)
问题:具有两个(或更多)多态参数的数据类型的实例的语法如何?
在函子类,这些都像实例Either a,((,) a或((->) r).我尝试了以下示例,但所有这些示例都被GHCi拒绝:
:t fmap @Either
:t fmap @(Either a)
:t fmap @(Either a b)
:t forall a. fmap @(Either a)
Run Code Online (Sandbox Code Playgroud) 以下函数通过使用递归方案库从列表实现良好的旧过滤器函数.
import Data.Functor.Foldable
catafilter :: (a -> Bool) -> [a] -> [a]
catafilter p = cata alg
where
-- alg :: ListF a [a] -> [a]
alg Nil = []
alg (Cons x xs) = if (p x) then x : xs else xs
Run Code Online (Sandbox Code Playgroud)
它编译和短期测试就像catafilter odd [1,2,3,4]是成功的.但是,如果我取消注释类型签名,alg我会收到以下错误:
src/cata.hs:8:30: error:
• Couldn't match expected type ‘a’ with actual type ‘a1’
‘a1’ is a rigid type variable bound by
the type signature for:
alg …Run Code Online (Sandbox Code Playgroud) 为了学习如何编写更通用的代码,我尝试编写一个简单的Array类.我们的想法是只使用Array类提供的函数编写一些简单的数组操作,然后将不同的数据类型写为实例.所以我想写出不同的数组表示.
对于第一次尝试,数组具有多个行和列以及可折叠的容器.
module Array where
import qualified Data.Vector as V
import Data.Foldable
class Array arr where
aRows :: arr a -> Int
aCols :: arr a -> Int
aData :: Foldable t => arr a -> t a
data VectorArray a = VectorArray
{ vRows :: !Int
, vCols :: !Int
, vData :: !(V.Vector a)}
instance Array VectorArray where
aRows = vRows
aCols = vCols
aData = vData
Run Code Online (Sandbox Code Playgroud)
最后一行不编译:
• Couldn't match type ‘t’ with ‘V.Vector’
‘t’ is a …Run Code Online (Sandbox Code Playgroud) 类类Data.Foldable具有以下定义:
class Foldable t where
{-# MINIMAL foldMap | foldr #-}
foldMap :: Monoid m => (a -> m) -> t a -> m
foldr :: (a -> b -> b) -> b -> t a -> b
....
<more definitions>
Run Code Online (Sandbox Code Playgroud)
最小的节说,我可以用foldr函数定义一个实例.在我可以编译的所有示例中,foldr函数都有类型a -> a -> a.但是我无法定义折叠函数真正键入a -> b -> b哪些类型a和b
不同的东西.
以下代码显示了一个不编译的示例:
import Data.Foldable
data Tree a = Tree a a | Leaf a
class Size a …Run Code Online (Sandbox Code Playgroud)