簡體   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