繁体   English   中英

在 Haskell 中组合具有中间多态类型的函数

[英]Composing functions with a intermediate polymorphic type in Haskell

我有以下文件:

module SimpleComposition where

class Intermediate a where
    f :: a -> Int
    g :: Char -> a

h :: Char -> Int
h = f . g

尝试在 ghci 中加载它时,出现错误:

main.hs:8:5: error:
    * No instance for (Intermediate a0) arising from a use of `f'
    * In the first argument of `(.)', namely `f'
      In the expression: f . g
      In an equation for `h': h = f . g
  |
8 | h = f . g
  |     ^

我认为问题在于有人可能会使用 2 种不同类型,它们是此组合中的Intermediate实例。 当我导出这个模块时,我如何保证它是一样的?

PS:这是一个比我之前提出的问题更好的最小示例(如何在 Haskell 中组合多态函数? )。

问题不在于无法推断出实例,而是编译器确实无法知道您可能想要的类型。 g可以产生任何向它询问的类型(前提是它有一个Intermediate实例), f可以使用任何这样的类型......但没有人指定哪一个

但这很容易解决:现在只需 select 一个类型。 当然,它必须是有实例的; 例如,如果你有

instance Intermediate Char where
  f = fromEnum
  g = id

那么你可以使用

h :: Char -> Int
h = (f :: Char -> Int) . g

修复类型选择的更简洁的方法是使用语法扩展:

{-# LANGUAGE TypeApplications #-}

h = f @Char . g

...或者,为了强调您只是在中间固定类型,

h = f . id @Char . g

我认为问题在于有人可能会使用 2 种不同类型,它们是此组合中的中间实例。

没有问题是 Haskell 不能再从签名派生什么a要使用。 假设有两种Intermediate类型:

instance Intermediate Char where
    # …

instance Intermediate Bool where
    # …

现在h有两种实现:

h :: Char -> Int
h = f . (g :: Char -> Char)

或者:

h :: Char -> Int
h = f . (g :: Char -> Bool)

可以使用无数种Intermediate类型。 问题是 Haskell 无法根据类型签名判断使用什么类型。

我们可以给它一个类型提示,但这当然意味着中间类型是固定的。

解决此问题的一种简单方法是使用asTypeOf:: a -> a -> a 这基本上是一个const function,但是两个参数具有相同的类型。 因此,这用于添加提示要使用什么类型,例如:

h :: Intermediate a => a -> Char -> Int
h a x = f (g x `asTypeOf` a)

因此,此处参数a并不重要,这是一种“注入”类型的方法,该类型将用作g的结果和f的参数的类型。

如果您以后使用h ,您可以使用:

h (undefined :: Char) 'a'

指定f应该具有类型Char -> Char ,并且g应该具有类型Char -> Int

就像@leftroundabout@DanielWagner说的那样,不使用这种虚拟变量的更干净的解决方案是在签名中添加类型变量:

{-# LANGUAGE AllowAmbiguousTypes, ScopedTypeVariables, TypeApplications #-}

h :: forall a. Intermediate a => Char -> Int
h = f . g @ a

然后我们可以将h与类型变量一起使用:

h @ Char 'a'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM