Haskell 函数签名中具有多个类型变量的类型约束

问题描述 投票:0回答:2

我一直在文档和维基上搜索 Haskell 在函数签名中的类型约束。不幸的是,我找不到满意的答案。

此时,我认为自己是初学者,所以如果您看到滥用技术术语或缺乏关于该主题的高级知识,我想请教您的理解。

第一个场景

考虑下面函数签名给出的真实示例:

count :: (Eq e, Num n) => e -> [e] -> n -> n

这个函数有类型约束:

Eq
Num
,每个都有一个变量,分别是:
e
n
。我也可以提供一个只有一个约束的更简单的签名(例如
foo :: Eq a => a -> Bool
)。

但是接下来呢?

第二种情况

考虑假设的例子。我想到他们试图表示属于同一类型约束的多个变量。

-- As far as I tested, the examples below are incorrect
-- and do not reflect proper Haskell syntax

foo :: (Num a b c) => use the variables here

or

foo :: Num a, b, c => use the variables here

我们可以在同一约束中指定多个变量吗,就像我上面尝试的那样?我必须单独指定它们吗?

foo :: Eq a, Eq b ... => use the variables here

有没有一种情况会使用多个相同类型的类型变量,这会带来什么影响?

haskell types constraints type-variables function-signature
2个回答
2
投票

您还可以定义一个类型族来约束列表中的每个元素:

{-# LANGUAGE DataKinds, TypeFamilies #-}

import Data.Kind (Constraint)

type
  AllCls :: (k -> Constraint) -> ([k] -> Constraint)
type family
  AllCls cls as where
  AllCls cls '[]    = ()
  AllCls cls (a:as) = (cls a, AllCls cls as)

allEqual :: AllCls Eq [a, b, c] => a -> a -> b -> b -> c -> c -> Bool
allEqual x1 x2 y1 y2 z1 z2 = and
  [ x1 == x2
  , y1 == y2
  , z1 == z2
  ]

1
投票

你可以写一个类型同义词,让你可以约束很多类型,而不必每次都重复约束,就像这样:

import Data.Kind (Constraint)

type Three c t1 t2 t3 = (c t1, c t2, c t3) :: Constraint

allEqual :: Three Eq a b c => a -> a -> b -> b -> c -> c -> Bool
allEqual x1 x2 y1 y2 z1 z2 = x1 == x2 && y1 == y2 && z1 == z2
© www.soinside.com 2019 - 2024. All rights reserved.