zwvista

导航

Haskell语言学习笔记(97)Phantom Type

示例

Named typeclasses in Haskell

{-# LANGUAGE AllowAmbiguousTypes     #-}
{-# LANGUAGE MultiParamTypeClasses   #-}
{-# LANGUAGE FlexibleInstances       #-}
{-# LANGUAGE ScopedTypeVariables     #-}
{-# LANGUAGE TypeApplications        #-}

module NamedTypeclass where

import Prelude hiding (Monoid, mempty, (<>))

data Sum
data Product

class Monoid b a where
  (<>)   :: a -> a -> a
  mempty :: a

instance Monoid Sum Int where
  x <> y = x + y
  mempty = 0

instance Monoid Product Int where
  x <> y = x * y
  mempty = 1

instance Monoid b [a] where
  x <> y = x ++ y
  mempty = []

fold :: forall b a . Monoid b a => [a] -> a
fold []       = mempty @b
fold (x : xs) = (<>) @b x (fold @b xs)

sum :: [Int] -> Int
sum = fold @Sum

product :: [Int] -> Int
product = fold @Product

concat :: [[a]] -> [a]
concat = fold
*NamedTypeclass> NamedTypeclass.sum [1,2,3,4]
10
*NamedTypeclass> NamedTypeclass.product [1,2,3,4]
24
*NamedTypeclass> NamedTypeclass.concat [[1],[2]]
[1,2]

Phantom Type

Phantom type
WHAT I WISH I KNEW WHEN LEARNING HASKELL - Phantom Types

AllowAmbiguousTypes

{-# LANGUAGE AllowAmbiguousTypes #-}
允许类型签名中的类型不出现在定义中,此时该类型为模糊(Ambiguous)类型,而所定义的类型被称为虚无(Phantom)类型。
示例中
class Monoid b a
的 b 就没有出现在定义中,因而 b 是模糊类型,Monoid 是虚无类型。

Empty Type

示例中
data Sum
该类型没有实体,是 Empty Type。

MultiParamTypeClasses

{-# LANGUAGE MultiParamTypeClasses #-}
允许类型类的定义中包含一个以上的参数。
示例中
class Monoid b a
的类型签名中含有两个类型参数 b 和 a。

FlexibleInstances

{-# LANGUAGE FlexibleInstances #-}
允许类型实例的类型签名中包含类型别名或嵌套类型。
示例中
instance Monoid b [a]
的类型签名中含有嵌套类型 [a]。

ExplicitForAll

{-# LANGUAGE ExplicitForAll #-}
允许显式使用 forall

ScopedTypeVariables

{-# LANGUAGE ScopedTypeVariables #-}
允许 forall 所引进的类型变量用作类型修饰。
示例中
fold :: forall b a . Monoid b a => [a] -> a
的类型签名中 forall 所声明的两个类型参数 b 和 a。

TypeApplications

{-# LANGUAGE TypeApplications #-}
允许使用类型应用程序(Type Application)的语法。
使用 TypeApplications 可以将某个多态函数应用到某个具体类型上(该类型前需要加上 @)
相当于在别的语言中调用泛型函数时指定类型参数。

Prelude> :set -XTypeApplications
Prelude> show (read @Int "5")
"5"

示例中
sum = fold @Sum
将 fold 函数的类型变量 b 指定为类型实例 Sum

Visible type applications

posted on 2020-05-13 09:30  zwvista  阅读(312)  评论(0编辑  收藏  举报